1*0b57cec5SDimitry Andric //===-- SparcISelLowering.cpp - Sparc DAG Lowering Implementation ---------===// 2*0b57cec5SDimitry Andric // 3*0b57cec5SDimitry Andric // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 4*0b57cec5SDimitry Andric // See https://llvm.org/LICENSE.txt for license information. 5*0b57cec5SDimitry Andric // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 6*0b57cec5SDimitry Andric // 7*0b57cec5SDimitry Andric //===----------------------------------------------------------------------===// 8*0b57cec5SDimitry Andric // 9*0b57cec5SDimitry Andric // This file implements the interfaces that Sparc uses to lower LLVM code into a 10*0b57cec5SDimitry Andric // selection DAG. 11*0b57cec5SDimitry Andric // 12*0b57cec5SDimitry Andric //===----------------------------------------------------------------------===// 13*0b57cec5SDimitry Andric 14*0b57cec5SDimitry Andric #include "SparcISelLowering.h" 15*0b57cec5SDimitry Andric #include "MCTargetDesc/SparcMCExpr.h" 16*0b57cec5SDimitry Andric #include "SparcMachineFunctionInfo.h" 17*0b57cec5SDimitry Andric #include "SparcRegisterInfo.h" 18*0b57cec5SDimitry Andric #include "SparcTargetMachine.h" 19*0b57cec5SDimitry Andric #include "SparcTargetObjectFile.h" 20*0b57cec5SDimitry Andric #include "llvm/ADT/StringExtras.h" 21*0b57cec5SDimitry Andric #include "llvm/ADT/StringSwitch.h" 22*0b57cec5SDimitry Andric #include "llvm/CodeGen/CallingConvLower.h" 23*0b57cec5SDimitry Andric #include "llvm/CodeGen/MachineFrameInfo.h" 24*0b57cec5SDimitry Andric #include "llvm/CodeGen/MachineFunction.h" 25*0b57cec5SDimitry Andric #include "llvm/CodeGen/MachineInstrBuilder.h" 26*0b57cec5SDimitry Andric #include "llvm/CodeGen/MachineRegisterInfo.h" 27*0b57cec5SDimitry Andric #include "llvm/CodeGen/SelectionDAG.h" 28*0b57cec5SDimitry Andric #include "llvm/CodeGen/TargetLoweringObjectFileImpl.h" 29*0b57cec5SDimitry Andric #include "llvm/IR/DerivedTypes.h" 30*0b57cec5SDimitry Andric #include "llvm/IR/Function.h" 31*0b57cec5SDimitry Andric #include "llvm/IR/Module.h" 32*0b57cec5SDimitry Andric #include "llvm/Support/ErrorHandling.h" 33*0b57cec5SDimitry Andric #include "llvm/Support/KnownBits.h" 34*0b57cec5SDimitry Andric using namespace llvm; 35*0b57cec5SDimitry Andric 36*0b57cec5SDimitry Andric 37*0b57cec5SDimitry Andric //===----------------------------------------------------------------------===// 38*0b57cec5SDimitry Andric // Calling Convention Implementation 39*0b57cec5SDimitry Andric //===----------------------------------------------------------------------===// 40*0b57cec5SDimitry Andric 41*0b57cec5SDimitry Andric static bool CC_Sparc_Assign_SRet(unsigned &ValNo, MVT &ValVT, 42*0b57cec5SDimitry Andric MVT &LocVT, CCValAssign::LocInfo &LocInfo, 43*0b57cec5SDimitry Andric ISD::ArgFlagsTy &ArgFlags, CCState &State) 44*0b57cec5SDimitry Andric { 45*0b57cec5SDimitry Andric assert (ArgFlags.isSRet()); 46*0b57cec5SDimitry Andric 47*0b57cec5SDimitry Andric // Assign SRet argument. 48*0b57cec5SDimitry Andric State.addLoc(CCValAssign::getCustomMem(ValNo, ValVT, 49*0b57cec5SDimitry Andric 0, 50*0b57cec5SDimitry Andric LocVT, LocInfo)); 51*0b57cec5SDimitry Andric return true; 52*0b57cec5SDimitry Andric } 53*0b57cec5SDimitry Andric 54*0b57cec5SDimitry Andric static bool CC_Sparc_Assign_Split_64(unsigned &ValNo, MVT &ValVT, 55*0b57cec5SDimitry Andric MVT &LocVT, CCValAssign::LocInfo &LocInfo, 56*0b57cec5SDimitry Andric ISD::ArgFlagsTy &ArgFlags, CCState &State) 57*0b57cec5SDimitry Andric { 58*0b57cec5SDimitry Andric static const MCPhysReg RegList[] = { 59*0b57cec5SDimitry Andric SP::I0, SP::I1, SP::I2, SP::I3, SP::I4, SP::I5 60*0b57cec5SDimitry Andric }; 61*0b57cec5SDimitry Andric // Try to get first reg. 62*0b57cec5SDimitry Andric if (unsigned Reg = State.AllocateReg(RegList)) { 63*0b57cec5SDimitry Andric State.addLoc(CCValAssign::getCustomReg(ValNo, ValVT, Reg, LocVT, LocInfo)); 64*0b57cec5SDimitry Andric } else { 65*0b57cec5SDimitry Andric // Assign whole thing in stack. 66*0b57cec5SDimitry Andric State.addLoc(CCValAssign::getCustomMem(ValNo, ValVT, 67*0b57cec5SDimitry Andric State.AllocateStack(8,4), 68*0b57cec5SDimitry Andric LocVT, LocInfo)); 69*0b57cec5SDimitry Andric return true; 70*0b57cec5SDimitry Andric } 71*0b57cec5SDimitry Andric 72*0b57cec5SDimitry Andric // Try to get second reg. 73*0b57cec5SDimitry Andric if (unsigned Reg = State.AllocateReg(RegList)) 74*0b57cec5SDimitry Andric State.addLoc(CCValAssign::getCustomReg(ValNo, ValVT, Reg, LocVT, LocInfo)); 75*0b57cec5SDimitry Andric else 76*0b57cec5SDimitry Andric State.addLoc(CCValAssign::getCustomMem(ValNo, ValVT, 77*0b57cec5SDimitry Andric State.AllocateStack(4,4), 78*0b57cec5SDimitry Andric LocVT, LocInfo)); 79*0b57cec5SDimitry Andric return true; 80*0b57cec5SDimitry Andric } 81*0b57cec5SDimitry Andric 82*0b57cec5SDimitry Andric static bool CC_Sparc_Assign_Ret_Split_64(unsigned &ValNo, MVT &ValVT, 83*0b57cec5SDimitry Andric MVT &LocVT, CCValAssign::LocInfo &LocInfo, 84*0b57cec5SDimitry Andric ISD::ArgFlagsTy &ArgFlags, CCState &State) 85*0b57cec5SDimitry Andric { 86*0b57cec5SDimitry Andric static const MCPhysReg RegList[] = { 87*0b57cec5SDimitry Andric SP::I0, SP::I1, SP::I2, SP::I3, SP::I4, SP::I5 88*0b57cec5SDimitry Andric }; 89*0b57cec5SDimitry Andric 90*0b57cec5SDimitry Andric // Try to get first reg. 91*0b57cec5SDimitry Andric if (unsigned Reg = State.AllocateReg(RegList)) 92*0b57cec5SDimitry Andric State.addLoc(CCValAssign::getCustomReg(ValNo, ValVT, Reg, LocVT, LocInfo)); 93*0b57cec5SDimitry Andric else 94*0b57cec5SDimitry Andric return false; 95*0b57cec5SDimitry Andric 96*0b57cec5SDimitry Andric // Try to get second reg. 97*0b57cec5SDimitry Andric if (unsigned Reg = State.AllocateReg(RegList)) 98*0b57cec5SDimitry Andric State.addLoc(CCValAssign::getCustomReg(ValNo, ValVT, Reg, LocVT, LocInfo)); 99*0b57cec5SDimitry Andric else 100*0b57cec5SDimitry Andric return false; 101*0b57cec5SDimitry Andric 102*0b57cec5SDimitry Andric return true; 103*0b57cec5SDimitry Andric } 104*0b57cec5SDimitry Andric 105*0b57cec5SDimitry Andric // Allocate a full-sized argument for the 64-bit ABI. 106*0b57cec5SDimitry Andric static bool CC_Sparc64_Full(unsigned &ValNo, MVT &ValVT, 107*0b57cec5SDimitry Andric MVT &LocVT, CCValAssign::LocInfo &LocInfo, 108*0b57cec5SDimitry Andric ISD::ArgFlagsTy &ArgFlags, CCState &State) { 109*0b57cec5SDimitry Andric assert((LocVT == MVT::f32 || LocVT == MVT::f128 110*0b57cec5SDimitry Andric || LocVT.getSizeInBits() == 64) && 111*0b57cec5SDimitry Andric "Can't handle non-64 bits locations"); 112*0b57cec5SDimitry Andric 113*0b57cec5SDimitry Andric // Stack space is allocated for all arguments starting from [%fp+BIAS+128]. 114*0b57cec5SDimitry Andric unsigned size = (LocVT == MVT::f128) ? 16 : 8; 115*0b57cec5SDimitry Andric unsigned alignment = (LocVT == MVT::f128) ? 16 : 8; 116*0b57cec5SDimitry Andric unsigned Offset = State.AllocateStack(size, alignment); 117*0b57cec5SDimitry Andric unsigned Reg = 0; 118*0b57cec5SDimitry Andric 119*0b57cec5SDimitry Andric if (LocVT == MVT::i64 && Offset < 6*8) 120*0b57cec5SDimitry Andric // Promote integers to %i0-%i5. 121*0b57cec5SDimitry Andric Reg = SP::I0 + Offset/8; 122*0b57cec5SDimitry Andric else if (LocVT == MVT::f64 && Offset < 16*8) 123*0b57cec5SDimitry Andric // Promote doubles to %d0-%d30. (Which LLVM calls D0-D15). 124*0b57cec5SDimitry Andric Reg = SP::D0 + Offset/8; 125*0b57cec5SDimitry Andric else if (LocVT == MVT::f32 && Offset < 16*8) 126*0b57cec5SDimitry Andric // Promote floats to %f1, %f3, ... 127*0b57cec5SDimitry Andric Reg = SP::F1 + Offset/4; 128*0b57cec5SDimitry Andric else if (LocVT == MVT::f128 && Offset < 16*8) 129*0b57cec5SDimitry Andric // Promote long doubles to %q0-%q28. (Which LLVM calls Q0-Q7). 130*0b57cec5SDimitry Andric Reg = SP::Q0 + Offset/16; 131*0b57cec5SDimitry Andric 132*0b57cec5SDimitry Andric // Promote to register when possible, otherwise use the stack slot. 133*0b57cec5SDimitry Andric if (Reg) { 134*0b57cec5SDimitry Andric State.addLoc(CCValAssign::getReg(ValNo, ValVT, Reg, LocVT, LocInfo)); 135*0b57cec5SDimitry Andric return true; 136*0b57cec5SDimitry Andric } 137*0b57cec5SDimitry Andric 138*0b57cec5SDimitry Andric // This argument goes on the stack in an 8-byte slot. 139*0b57cec5SDimitry Andric // When passing floats, LocVT is smaller than 8 bytes. Adjust the offset to 140*0b57cec5SDimitry Andric // the right-aligned float. The first 4 bytes of the stack slot are undefined. 141*0b57cec5SDimitry Andric if (LocVT == MVT::f32) 142*0b57cec5SDimitry Andric Offset += 4; 143*0b57cec5SDimitry Andric 144*0b57cec5SDimitry Andric State.addLoc(CCValAssign::getMem(ValNo, ValVT, Offset, LocVT, LocInfo)); 145*0b57cec5SDimitry Andric return true; 146*0b57cec5SDimitry Andric } 147*0b57cec5SDimitry Andric 148*0b57cec5SDimitry Andric // Allocate a half-sized argument for the 64-bit ABI. 149*0b57cec5SDimitry Andric // 150*0b57cec5SDimitry Andric // This is used when passing { float, int } structs by value in registers. 151*0b57cec5SDimitry Andric static bool CC_Sparc64_Half(unsigned &ValNo, MVT &ValVT, 152*0b57cec5SDimitry Andric MVT &LocVT, CCValAssign::LocInfo &LocInfo, 153*0b57cec5SDimitry Andric ISD::ArgFlagsTy &ArgFlags, CCState &State) { 154*0b57cec5SDimitry Andric assert(LocVT.getSizeInBits() == 32 && "Can't handle non-32 bits locations"); 155*0b57cec5SDimitry Andric unsigned Offset = State.AllocateStack(4, 4); 156*0b57cec5SDimitry Andric 157*0b57cec5SDimitry Andric if (LocVT == MVT::f32 && Offset < 16*8) { 158*0b57cec5SDimitry Andric // Promote floats to %f0-%f31. 159*0b57cec5SDimitry Andric State.addLoc(CCValAssign::getReg(ValNo, ValVT, SP::F0 + Offset/4, 160*0b57cec5SDimitry Andric LocVT, LocInfo)); 161*0b57cec5SDimitry Andric return true; 162*0b57cec5SDimitry Andric } 163*0b57cec5SDimitry Andric 164*0b57cec5SDimitry Andric if (LocVT == MVT::i32 && Offset < 6*8) { 165*0b57cec5SDimitry Andric // Promote integers to %i0-%i5, using half the register. 166*0b57cec5SDimitry Andric unsigned Reg = SP::I0 + Offset/8; 167*0b57cec5SDimitry Andric LocVT = MVT::i64; 168*0b57cec5SDimitry Andric LocInfo = CCValAssign::AExt; 169*0b57cec5SDimitry Andric 170*0b57cec5SDimitry Andric // Set the Custom bit if this i32 goes in the high bits of a register. 171*0b57cec5SDimitry Andric if (Offset % 8 == 0) 172*0b57cec5SDimitry Andric State.addLoc(CCValAssign::getCustomReg(ValNo, ValVT, Reg, 173*0b57cec5SDimitry Andric LocVT, LocInfo)); 174*0b57cec5SDimitry Andric else 175*0b57cec5SDimitry Andric State.addLoc(CCValAssign::getReg(ValNo, ValVT, Reg, LocVT, LocInfo)); 176*0b57cec5SDimitry Andric return true; 177*0b57cec5SDimitry Andric } 178*0b57cec5SDimitry Andric 179*0b57cec5SDimitry Andric State.addLoc(CCValAssign::getMem(ValNo, ValVT, Offset, LocVT, LocInfo)); 180*0b57cec5SDimitry Andric return true; 181*0b57cec5SDimitry Andric } 182*0b57cec5SDimitry Andric 183*0b57cec5SDimitry Andric #include "SparcGenCallingConv.inc" 184*0b57cec5SDimitry Andric 185*0b57cec5SDimitry Andric // The calling conventions in SparcCallingConv.td are described in terms of the 186*0b57cec5SDimitry Andric // callee's register window. This function translates registers to the 187*0b57cec5SDimitry Andric // corresponding caller window %o register. 188*0b57cec5SDimitry Andric static unsigned toCallerWindow(unsigned Reg) { 189*0b57cec5SDimitry Andric static_assert(SP::I0 + 7 == SP::I7 && SP::O0 + 7 == SP::O7, 190*0b57cec5SDimitry Andric "Unexpected enum"); 191*0b57cec5SDimitry Andric if (Reg >= SP::I0 && Reg <= SP::I7) 192*0b57cec5SDimitry Andric return Reg - SP::I0 + SP::O0; 193*0b57cec5SDimitry Andric return Reg; 194*0b57cec5SDimitry Andric } 195*0b57cec5SDimitry Andric 196*0b57cec5SDimitry Andric SDValue 197*0b57cec5SDimitry Andric SparcTargetLowering::LowerReturn(SDValue Chain, CallingConv::ID CallConv, 198*0b57cec5SDimitry Andric bool IsVarArg, 199*0b57cec5SDimitry Andric const SmallVectorImpl<ISD::OutputArg> &Outs, 200*0b57cec5SDimitry Andric const SmallVectorImpl<SDValue> &OutVals, 201*0b57cec5SDimitry Andric const SDLoc &DL, SelectionDAG &DAG) const { 202*0b57cec5SDimitry Andric if (Subtarget->is64Bit()) 203*0b57cec5SDimitry Andric return LowerReturn_64(Chain, CallConv, IsVarArg, Outs, OutVals, DL, DAG); 204*0b57cec5SDimitry Andric return LowerReturn_32(Chain, CallConv, IsVarArg, Outs, OutVals, DL, DAG); 205*0b57cec5SDimitry Andric } 206*0b57cec5SDimitry Andric 207*0b57cec5SDimitry Andric SDValue 208*0b57cec5SDimitry Andric SparcTargetLowering::LowerReturn_32(SDValue Chain, CallingConv::ID CallConv, 209*0b57cec5SDimitry Andric bool IsVarArg, 210*0b57cec5SDimitry Andric const SmallVectorImpl<ISD::OutputArg> &Outs, 211*0b57cec5SDimitry Andric const SmallVectorImpl<SDValue> &OutVals, 212*0b57cec5SDimitry Andric const SDLoc &DL, SelectionDAG &DAG) const { 213*0b57cec5SDimitry Andric MachineFunction &MF = DAG.getMachineFunction(); 214*0b57cec5SDimitry Andric 215*0b57cec5SDimitry Andric // CCValAssign - represent the assignment of the return value to locations. 216*0b57cec5SDimitry Andric SmallVector<CCValAssign, 16> RVLocs; 217*0b57cec5SDimitry Andric 218*0b57cec5SDimitry Andric // CCState - Info about the registers and stack slot. 219*0b57cec5SDimitry Andric CCState CCInfo(CallConv, IsVarArg, DAG.getMachineFunction(), RVLocs, 220*0b57cec5SDimitry Andric *DAG.getContext()); 221*0b57cec5SDimitry Andric 222*0b57cec5SDimitry Andric // Analyze return values. 223*0b57cec5SDimitry Andric CCInfo.AnalyzeReturn(Outs, RetCC_Sparc32); 224*0b57cec5SDimitry Andric 225*0b57cec5SDimitry Andric SDValue Flag; 226*0b57cec5SDimitry Andric SmallVector<SDValue, 4> RetOps(1, Chain); 227*0b57cec5SDimitry Andric // Make room for the return address offset. 228*0b57cec5SDimitry Andric RetOps.push_back(SDValue()); 229*0b57cec5SDimitry Andric 230*0b57cec5SDimitry Andric // Copy the result values into the output registers. 231*0b57cec5SDimitry Andric for (unsigned i = 0, realRVLocIdx = 0; 232*0b57cec5SDimitry Andric i != RVLocs.size(); 233*0b57cec5SDimitry Andric ++i, ++realRVLocIdx) { 234*0b57cec5SDimitry Andric CCValAssign &VA = RVLocs[i]; 235*0b57cec5SDimitry Andric assert(VA.isRegLoc() && "Can only return in registers!"); 236*0b57cec5SDimitry Andric 237*0b57cec5SDimitry Andric SDValue Arg = OutVals[realRVLocIdx]; 238*0b57cec5SDimitry Andric 239*0b57cec5SDimitry Andric if (VA.needsCustom()) { 240*0b57cec5SDimitry Andric assert(VA.getLocVT() == MVT::v2i32); 241*0b57cec5SDimitry Andric // Legalize ret v2i32 -> ret 2 x i32 (Basically: do what would 242*0b57cec5SDimitry Andric // happen by default if this wasn't a legal type) 243*0b57cec5SDimitry Andric 244*0b57cec5SDimitry Andric SDValue Part0 = DAG.getNode(ISD::EXTRACT_VECTOR_ELT, DL, MVT::i32, 245*0b57cec5SDimitry Andric Arg, 246*0b57cec5SDimitry Andric DAG.getConstant(0, DL, getVectorIdxTy(DAG.getDataLayout()))); 247*0b57cec5SDimitry Andric SDValue Part1 = DAG.getNode(ISD::EXTRACT_VECTOR_ELT, DL, MVT::i32, 248*0b57cec5SDimitry Andric Arg, 249*0b57cec5SDimitry Andric DAG.getConstant(1, DL, getVectorIdxTy(DAG.getDataLayout()))); 250*0b57cec5SDimitry Andric 251*0b57cec5SDimitry Andric Chain = DAG.getCopyToReg(Chain, DL, VA.getLocReg(), Part0, Flag); 252*0b57cec5SDimitry Andric Flag = Chain.getValue(1); 253*0b57cec5SDimitry Andric RetOps.push_back(DAG.getRegister(VA.getLocReg(), VA.getLocVT())); 254*0b57cec5SDimitry Andric VA = RVLocs[++i]; // skip ahead to next loc 255*0b57cec5SDimitry Andric Chain = DAG.getCopyToReg(Chain, DL, VA.getLocReg(), Part1, 256*0b57cec5SDimitry Andric Flag); 257*0b57cec5SDimitry Andric } else 258*0b57cec5SDimitry Andric Chain = DAG.getCopyToReg(Chain, DL, VA.getLocReg(), Arg, Flag); 259*0b57cec5SDimitry Andric 260*0b57cec5SDimitry Andric // Guarantee that all emitted copies are stuck together with flags. 261*0b57cec5SDimitry Andric Flag = Chain.getValue(1); 262*0b57cec5SDimitry Andric RetOps.push_back(DAG.getRegister(VA.getLocReg(), VA.getLocVT())); 263*0b57cec5SDimitry Andric } 264*0b57cec5SDimitry Andric 265*0b57cec5SDimitry Andric unsigned RetAddrOffset = 8; // Call Inst + Delay Slot 266*0b57cec5SDimitry Andric // If the function returns a struct, copy the SRetReturnReg to I0 267*0b57cec5SDimitry Andric if (MF.getFunction().hasStructRetAttr()) { 268*0b57cec5SDimitry Andric SparcMachineFunctionInfo *SFI = MF.getInfo<SparcMachineFunctionInfo>(); 269*0b57cec5SDimitry Andric unsigned Reg = SFI->getSRetReturnReg(); 270*0b57cec5SDimitry Andric if (!Reg) 271*0b57cec5SDimitry Andric llvm_unreachable("sret virtual register not created in the entry block"); 272*0b57cec5SDimitry Andric auto PtrVT = getPointerTy(DAG.getDataLayout()); 273*0b57cec5SDimitry Andric SDValue Val = DAG.getCopyFromReg(Chain, DL, Reg, PtrVT); 274*0b57cec5SDimitry Andric Chain = DAG.getCopyToReg(Chain, DL, SP::I0, Val, Flag); 275*0b57cec5SDimitry Andric Flag = Chain.getValue(1); 276*0b57cec5SDimitry Andric RetOps.push_back(DAG.getRegister(SP::I0, PtrVT)); 277*0b57cec5SDimitry Andric RetAddrOffset = 12; // CallInst + Delay Slot + Unimp 278*0b57cec5SDimitry Andric } 279*0b57cec5SDimitry Andric 280*0b57cec5SDimitry Andric RetOps[0] = Chain; // Update chain. 281*0b57cec5SDimitry Andric RetOps[1] = DAG.getConstant(RetAddrOffset, DL, MVT::i32); 282*0b57cec5SDimitry Andric 283*0b57cec5SDimitry Andric // Add the flag if we have it. 284*0b57cec5SDimitry Andric if (Flag.getNode()) 285*0b57cec5SDimitry Andric RetOps.push_back(Flag); 286*0b57cec5SDimitry Andric 287*0b57cec5SDimitry Andric return DAG.getNode(SPISD::RET_FLAG, DL, MVT::Other, RetOps); 288*0b57cec5SDimitry Andric } 289*0b57cec5SDimitry Andric 290*0b57cec5SDimitry Andric // Lower return values for the 64-bit ABI. 291*0b57cec5SDimitry Andric // Return values are passed the exactly the same way as function arguments. 292*0b57cec5SDimitry Andric SDValue 293*0b57cec5SDimitry Andric SparcTargetLowering::LowerReturn_64(SDValue Chain, CallingConv::ID CallConv, 294*0b57cec5SDimitry Andric bool IsVarArg, 295*0b57cec5SDimitry Andric const SmallVectorImpl<ISD::OutputArg> &Outs, 296*0b57cec5SDimitry Andric const SmallVectorImpl<SDValue> &OutVals, 297*0b57cec5SDimitry Andric const SDLoc &DL, SelectionDAG &DAG) const { 298*0b57cec5SDimitry Andric // CCValAssign - represent the assignment of the return value to locations. 299*0b57cec5SDimitry Andric SmallVector<CCValAssign, 16> RVLocs; 300*0b57cec5SDimitry Andric 301*0b57cec5SDimitry Andric // CCState - Info about the registers and stack slot. 302*0b57cec5SDimitry Andric CCState CCInfo(CallConv, IsVarArg, DAG.getMachineFunction(), RVLocs, 303*0b57cec5SDimitry Andric *DAG.getContext()); 304*0b57cec5SDimitry Andric 305*0b57cec5SDimitry Andric // Analyze return values. 306*0b57cec5SDimitry Andric CCInfo.AnalyzeReturn(Outs, RetCC_Sparc64); 307*0b57cec5SDimitry Andric 308*0b57cec5SDimitry Andric SDValue Flag; 309*0b57cec5SDimitry Andric SmallVector<SDValue, 4> RetOps(1, Chain); 310*0b57cec5SDimitry Andric 311*0b57cec5SDimitry Andric // The second operand on the return instruction is the return address offset. 312*0b57cec5SDimitry Andric // The return address is always %i7+8 with the 64-bit ABI. 313*0b57cec5SDimitry Andric RetOps.push_back(DAG.getConstant(8, DL, MVT::i32)); 314*0b57cec5SDimitry Andric 315*0b57cec5SDimitry Andric // Copy the result values into the output registers. 316*0b57cec5SDimitry Andric for (unsigned i = 0; i != RVLocs.size(); ++i) { 317*0b57cec5SDimitry Andric CCValAssign &VA = RVLocs[i]; 318*0b57cec5SDimitry Andric assert(VA.isRegLoc() && "Can only return in registers!"); 319*0b57cec5SDimitry Andric SDValue OutVal = OutVals[i]; 320*0b57cec5SDimitry Andric 321*0b57cec5SDimitry Andric // Integer return values must be sign or zero extended by the callee. 322*0b57cec5SDimitry Andric switch (VA.getLocInfo()) { 323*0b57cec5SDimitry Andric case CCValAssign::Full: break; 324*0b57cec5SDimitry Andric case CCValAssign::SExt: 325*0b57cec5SDimitry Andric OutVal = DAG.getNode(ISD::SIGN_EXTEND, DL, VA.getLocVT(), OutVal); 326*0b57cec5SDimitry Andric break; 327*0b57cec5SDimitry Andric case CCValAssign::ZExt: 328*0b57cec5SDimitry Andric OutVal = DAG.getNode(ISD::ZERO_EXTEND, DL, VA.getLocVT(), OutVal); 329*0b57cec5SDimitry Andric break; 330*0b57cec5SDimitry Andric case CCValAssign::AExt: 331*0b57cec5SDimitry Andric OutVal = DAG.getNode(ISD::ANY_EXTEND, DL, VA.getLocVT(), OutVal); 332*0b57cec5SDimitry Andric break; 333*0b57cec5SDimitry Andric default: 334*0b57cec5SDimitry Andric llvm_unreachable("Unknown loc info!"); 335*0b57cec5SDimitry Andric } 336*0b57cec5SDimitry Andric 337*0b57cec5SDimitry Andric // The custom bit on an i32 return value indicates that it should be passed 338*0b57cec5SDimitry Andric // in the high bits of the register. 339*0b57cec5SDimitry Andric if (VA.getValVT() == MVT::i32 && VA.needsCustom()) { 340*0b57cec5SDimitry Andric OutVal = DAG.getNode(ISD::SHL, DL, MVT::i64, OutVal, 341*0b57cec5SDimitry Andric DAG.getConstant(32, DL, MVT::i32)); 342*0b57cec5SDimitry Andric 343*0b57cec5SDimitry Andric // The next value may go in the low bits of the same register. 344*0b57cec5SDimitry Andric // Handle both at once. 345*0b57cec5SDimitry Andric if (i+1 < RVLocs.size() && RVLocs[i+1].getLocReg() == VA.getLocReg()) { 346*0b57cec5SDimitry Andric SDValue NV = DAG.getNode(ISD::ZERO_EXTEND, DL, MVT::i64, OutVals[i+1]); 347*0b57cec5SDimitry Andric OutVal = DAG.getNode(ISD::OR, DL, MVT::i64, OutVal, NV); 348*0b57cec5SDimitry Andric // Skip the next value, it's already done. 349*0b57cec5SDimitry Andric ++i; 350*0b57cec5SDimitry Andric } 351*0b57cec5SDimitry Andric } 352*0b57cec5SDimitry Andric 353*0b57cec5SDimitry Andric Chain = DAG.getCopyToReg(Chain, DL, VA.getLocReg(), OutVal, Flag); 354*0b57cec5SDimitry Andric 355*0b57cec5SDimitry Andric // Guarantee that all emitted copies are stuck together with flags. 356*0b57cec5SDimitry Andric Flag = Chain.getValue(1); 357*0b57cec5SDimitry Andric RetOps.push_back(DAG.getRegister(VA.getLocReg(), VA.getLocVT())); 358*0b57cec5SDimitry Andric } 359*0b57cec5SDimitry Andric 360*0b57cec5SDimitry Andric RetOps[0] = Chain; // Update chain. 361*0b57cec5SDimitry Andric 362*0b57cec5SDimitry Andric // Add the flag if we have it. 363*0b57cec5SDimitry Andric if (Flag.getNode()) 364*0b57cec5SDimitry Andric RetOps.push_back(Flag); 365*0b57cec5SDimitry Andric 366*0b57cec5SDimitry Andric return DAG.getNode(SPISD::RET_FLAG, DL, MVT::Other, RetOps); 367*0b57cec5SDimitry Andric } 368*0b57cec5SDimitry Andric 369*0b57cec5SDimitry Andric SDValue SparcTargetLowering::LowerFormalArguments( 370*0b57cec5SDimitry Andric SDValue Chain, CallingConv::ID CallConv, bool IsVarArg, 371*0b57cec5SDimitry Andric const SmallVectorImpl<ISD::InputArg> &Ins, const SDLoc &DL, 372*0b57cec5SDimitry Andric SelectionDAG &DAG, SmallVectorImpl<SDValue> &InVals) const { 373*0b57cec5SDimitry Andric if (Subtarget->is64Bit()) 374*0b57cec5SDimitry Andric return LowerFormalArguments_64(Chain, CallConv, IsVarArg, Ins, 375*0b57cec5SDimitry Andric DL, DAG, InVals); 376*0b57cec5SDimitry Andric return LowerFormalArguments_32(Chain, CallConv, IsVarArg, Ins, 377*0b57cec5SDimitry Andric DL, DAG, InVals); 378*0b57cec5SDimitry Andric } 379*0b57cec5SDimitry Andric 380*0b57cec5SDimitry Andric /// LowerFormalArguments32 - V8 uses a very simple ABI, where all values are 381*0b57cec5SDimitry Andric /// passed in either one or two GPRs, including FP values. TODO: we should 382*0b57cec5SDimitry Andric /// pass FP values in FP registers for fastcc functions. 383*0b57cec5SDimitry Andric SDValue SparcTargetLowering::LowerFormalArguments_32( 384*0b57cec5SDimitry Andric SDValue Chain, CallingConv::ID CallConv, bool isVarArg, 385*0b57cec5SDimitry Andric const SmallVectorImpl<ISD::InputArg> &Ins, const SDLoc &dl, 386*0b57cec5SDimitry Andric SelectionDAG &DAG, SmallVectorImpl<SDValue> &InVals) const { 387*0b57cec5SDimitry Andric MachineFunction &MF = DAG.getMachineFunction(); 388*0b57cec5SDimitry Andric MachineRegisterInfo &RegInfo = MF.getRegInfo(); 389*0b57cec5SDimitry Andric SparcMachineFunctionInfo *FuncInfo = MF.getInfo<SparcMachineFunctionInfo>(); 390*0b57cec5SDimitry Andric 391*0b57cec5SDimitry Andric // Assign locations to all of the incoming arguments. 392*0b57cec5SDimitry Andric SmallVector<CCValAssign, 16> ArgLocs; 393*0b57cec5SDimitry Andric CCState CCInfo(CallConv, isVarArg, DAG.getMachineFunction(), ArgLocs, 394*0b57cec5SDimitry Andric *DAG.getContext()); 395*0b57cec5SDimitry Andric CCInfo.AnalyzeFormalArguments(Ins, CC_Sparc32); 396*0b57cec5SDimitry Andric 397*0b57cec5SDimitry Andric const unsigned StackOffset = 92; 398*0b57cec5SDimitry Andric bool IsLittleEndian = DAG.getDataLayout().isLittleEndian(); 399*0b57cec5SDimitry Andric 400*0b57cec5SDimitry Andric unsigned InIdx = 0; 401*0b57cec5SDimitry Andric for (unsigned i = 0, e = ArgLocs.size(); i != e; ++i, ++InIdx) { 402*0b57cec5SDimitry Andric CCValAssign &VA = ArgLocs[i]; 403*0b57cec5SDimitry Andric 404*0b57cec5SDimitry Andric if (Ins[InIdx].Flags.isSRet()) { 405*0b57cec5SDimitry Andric if (InIdx != 0) 406*0b57cec5SDimitry Andric report_fatal_error("sparc only supports sret on the first parameter"); 407*0b57cec5SDimitry Andric // Get SRet from [%fp+64]. 408*0b57cec5SDimitry Andric int FrameIdx = MF.getFrameInfo().CreateFixedObject(4, 64, true); 409*0b57cec5SDimitry Andric SDValue FIPtr = DAG.getFrameIndex(FrameIdx, MVT::i32); 410*0b57cec5SDimitry Andric SDValue Arg = 411*0b57cec5SDimitry Andric DAG.getLoad(MVT::i32, dl, Chain, FIPtr, MachinePointerInfo()); 412*0b57cec5SDimitry Andric InVals.push_back(Arg); 413*0b57cec5SDimitry Andric continue; 414*0b57cec5SDimitry Andric } 415*0b57cec5SDimitry Andric 416*0b57cec5SDimitry Andric if (VA.isRegLoc()) { 417*0b57cec5SDimitry Andric if (VA.needsCustom()) { 418*0b57cec5SDimitry Andric assert(VA.getLocVT() == MVT::f64 || VA.getLocVT() == MVT::v2i32); 419*0b57cec5SDimitry Andric 420*0b57cec5SDimitry Andric unsigned VRegHi = RegInfo.createVirtualRegister(&SP::IntRegsRegClass); 421*0b57cec5SDimitry Andric MF.getRegInfo().addLiveIn(VA.getLocReg(), VRegHi); 422*0b57cec5SDimitry Andric SDValue HiVal = DAG.getCopyFromReg(Chain, dl, VRegHi, MVT::i32); 423*0b57cec5SDimitry Andric 424*0b57cec5SDimitry Andric assert(i+1 < e); 425*0b57cec5SDimitry Andric CCValAssign &NextVA = ArgLocs[++i]; 426*0b57cec5SDimitry Andric 427*0b57cec5SDimitry Andric SDValue LoVal; 428*0b57cec5SDimitry Andric if (NextVA.isMemLoc()) { 429*0b57cec5SDimitry Andric int FrameIdx = MF.getFrameInfo(). 430*0b57cec5SDimitry Andric CreateFixedObject(4, StackOffset+NextVA.getLocMemOffset(),true); 431*0b57cec5SDimitry Andric SDValue FIPtr = DAG.getFrameIndex(FrameIdx, MVT::i32); 432*0b57cec5SDimitry Andric LoVal = DAG.getLoad(MVT::i32, dl, Chain, FIPtr, MachinePointerInfo()); 433*0b57cec5SDimitry Andric } else { 434*0b57cec5SDimitry Andric unsigned loReg = MF.addLiveIn(NextVA.getLocReg(), 435*0b57cec5SDimitry Andric &SP::IntRegsRegClass); 436*0b57cec5SDimitry Andric LoVal = DAG.getCopyFromReg(Chain, dl, loReg, MVT::i32); 437*0b57cec5SDimitry Andric } 438*0b57cec5SDimitry Andric 439*0b57cec5SDimitry Andric if (IsLittleEndian) 440*0b57cec5SDimitry Andric std::swap(LoVal, HiVal); 441*0b57cec5SDimitry Andric 442*0b57cec5SDimitry Andric SDValue WholeValue = 443*0b57cec5SDimitry Andric DAG.getNode(ISD::BUILD_PAIR, dl, MVT::i64, LoVal, HiVal); 444*0b57cec5SDimitry Andric WholeValue = DAG.getNode(ISD::BITCAST, dl, VA.getLocVT(), WholeValue); 445*0b57cec5SDimitry Andric InVals.push_back(WholeValue); 446*0b57cec5SDimitry Andric continue; 447*0b57cec5SDimitry Andric } 448*0b57cec5SDimitry Andric unsigned VReg = RegInfo.createVirtualRegister(&SP::IntRegsRegClass); 449*0b57cec5SDimitry Andric MF.getRegInfo().addLiveIn(VA.getLocReg(), VReg); 450*0b57cec5SDimitry Andric SDValue Arg = DAG.getCopyFromReg(Chain, dl, VReg, MVT::i32); 451*0b57cec5SDimitry Andric if (VA.getLocVT() == MVT::f32) 452*0b57cec5SDimitry Andric Arg = DAG.getNode(ISD::BITCAST, dl, MVT::f32, Arg); 453*0b57cec5SDimitry Andric else if (VA.getLocVT() != MVT::i32) { 454*0b57cec5SDimitry Andric Arg = DAG.getNode(ISD::AssertSext, dl, MVT::i32, Arg, 455*0b57cec5SDimitry Andric DAG.getValueType(VA.getLocVT())); 456*0b57cec5SDimitry Andric Arg = DAG.getNode(ISD::TRUNCATE, dl, VA.getLocVT(), Arg); 457*0b57cec5SDimitry Andric } 458*0b57cec5SDimitry Andric InVals.push_back(Arg); 459*0b57cec5SDimitry Andric continue; 460*0b57cec5SDimitry Andric } 461*0b57cec5SDimitry Andric 462*0b57cec5SDimitry Andric assert(VA.isMemLoc()); 463*0b57cec5SDimitry Andric 464*0b57cec5SDimitry Andric unsigned Offset = VA.getLocMemOffset()+StackOffset; 465*0b57cec5SDimitry Andric auto PtrVT = getPointerTy(DAG.getDataLayout()); 466*0b57cec5SDimitry Andric 467*0b57cec5SDimitry Andric if (VA.needsCustom()) { 468*0b57cec5SDimitry Andric assert(VA.getValVT() == MVT::f64 || VA.getValVT() == MVT::v2i32); 469*0b57cec5SDimitry Andric // If it is double-word aligned, just load. 470*0b57cec5SDimitry Andric if (Offset % 8 == 0) { 471*0b57cec5SDimitry Andric int FI = MF.getFrameInfo().CreateFixedObject(8, 472*0b57cec5SDimitry Andric Offset, 473*0b57cec5SDimitry Andric true); 474*0b57cec5SDimitry Andric SDValue FIPtr = DAG.getFrameIndex(FI, PtrVT); 475*0b57cec5SDimitry Andric SDValue Load = 476*0b57cec5SDimitry Andric DAG.getLoad(VA.getValVT(), dl, Chain, FIPtr, MachinePointerInfo()); 477*0b57cec5SDimitry Andric InVals.push_back(Load); 478*0b57cec5SDimitry Andric continue; 479*0b57cec5SDimitry Andric } 480*0b57cec5SDimitry Andric 481*0b57cec5SDimitry Andric int FI = MF.getFrameInfo().CreateFixedObject(4, 482*0b57cec5SDimitry Andric Offset, 483*0b57cec5SDimitry Andric true); 484*0b57cec5SDimitry Andric SDValue FIPtr = DAG.getFrameIndex(FI, PtrVT); 485*0b57cec5SDimitry Andric SDValue HiVal = 486*0b57cec5SDimitry Andric DAG.getLoad(MVT::i32, dl, Chain, FIPtr, MachinePointerInfo()); 487*0b57cec5SDimitry Andric int FI2 = MF.getFrameInfo().CreateFixedObject(4, 488*0b57cec5SDimitry Andric Offset+4, 489*0b57cec5SDimitry Andric true); 490*0b57cec5SDimitry Andric SDValue FIPtr2 = DAG.getFrameIndex(FI2, PtrVT); 491*0b57cec5SDimitry Andric 492*0b57cec5SDimitry Andric SDValue LoVal = 493*0b57cec5SDimitry Andric DAG.getLoad(MVT::i32, dl, Chain, FIPtr2, MachinePointerInfo()); 494*0b57cec5SDimitry Andric 495*0b57cec5SDimitry Andric if (IsLittleEndian) 496*0b57cec5SDimitry Andric std::swap(LoVal, HiVal); 497*0b57cec5SDimitry Andric 498*0b57cec5SDimitry Andric SDValue WholeValue = 499*0b57cec5SDimitry Andric DAG.getNode(ISD::BUILD_PAIR, dl, MVT::i64, LoVal, HiVal); 500*0b57cec5SDimitry Andric WholeValue = DAG.getNode(ISD::BITCAST, dl, VA.getValVT(), WholeValue); 501*0b57cec5SDimitry Andric InVals.push_back(WholeValue); 502*0b57cec5SDimitry Andric continue; 503*0b57cec5SDimitry Andric } 504*0b57cec5SDimitry Andric 505*0b57cec5SDimitry Andric int FI = MF.getFrameInfo().CreateFixedObject(4, 506*0b57cec5SDimitry Andric Offset, 507*0b57cec5SDimitry Andric true); 508*0b57cec5SDimitry Andric SDValue FIPtr = DAG.getFrameIndex(FI, PtrVT); 509*0b57cec5SDimitry Andric SDValue Load ; 510*0b57cec5SDimitry Andric if (VA.getValVT() == MVT::i32 || VA.getValVT() == MVT::f32) { 511*0b57cec5SDimitry Andric Load = DAG.getLoad(VA.getValVT(), dl, Chain, FIPtr, MachinePointerInfo()); 512*0b57cec5SDimitry Andric } else if (VA.getValVT() == MVT::f128) { 513*0b57cec5SDimitry Andric report_fatal_error("SPARCv8 does not handle f128 in calls; " 514*0b57cec5SDimitry Andric "pass indirectly"); 515*0b57cec5SDimitry Andric } else { 516*0b57cec5SDimitry Andric // We shouldn't see any other value types here. 517*0b57cec5SDimitry Andric llvm_unreachable("Unexpected ValVT encountered in frame lowering."); 518*0b57cec5SDimitry Andric } 519*0b57cec5SDimitry Andric InVals.push_back(Load); 520*0b57cec5SDimitry Andric } 521*0b57cec5SDimitry Andric 522*0b57cec5SDimitry Andric if (MF.getFunction().hasStructRetAttr()) { 523*0b57cec5SDimitry Andric // Copy the SRet Argument to SRetReturnReg. 524*0b57cec5SDimitry Andric SparcMachineFunctionInfo *SFI = MF.getInfo<SparcMachineFunctionInfo>(); 525*0b57cec5SDimitry Andric unsigned Reg = SFI->getSRetReturnReg(); 526*0b57cec5SDimitry Andric if (!Reg) { 527*0b57cec5SDimitry Andric Reg = MF.getRegInfo().createVirtualRegister(&SP::IntRegsRegClass); 528*0b57cec5SDimitry Andric SFI->setSRetReturnReg(Reg); 529*0b57cec5SDimitry Andric } 530*0b57cec5SDimitry Andric SDValue Copy = DAG.getCopyToReg(DAG.getEntryNode(), dl, Reg, InVals[0]); 531*0b57cec5SDimitry Andric Chain = DAG.getNode(ISD::TokenFactor, dl, MVT::Other, Copy, Chain); 532*0b57cec5SDimitry Andric } 533*0b57cec5SDimitry Andric 534*0b57cec5SDimitry Andric // Store remaining ArgRegs to the stack if this is a varargs function. 535*0b57cec5SDimitry Andric if (isVarArg) { 536*0b57cec5SDimitry Andric static const MCPhysReg ArgRegs[] = { 537*0b57cec5SDimitry Andric SP::I0, SP::I1, SP::I2, SP::I3, SP::I4, SP::I5 538*0b57cec5SDimitry Andric }; 539*0b57cec5SDimitry Andric unsigned NumAllocated = CCInfo.getFirstUnallocated(ArgRegs); 540*0b57cec5SDimitry Andric const MCPhysReg *CurArgReg = ArgRegs+NumAllocated, *ArgRegEnd = ArgRegs+6; 541*0b57cec5SDimitry Andric unsigned ArgOffset = CCInfo.getNextStackOffset(); 542*0b57cec5SDimitry Andric if (NumAllocated == 6) 543*0b57cec5SDimitry Andric ArgOffset += StackOffset; 544*0b57cec5SDimitry Andric else { 545*0b57cec5SDimitry Andric assert(!ArgOffset); 546*0b57cec5SDimitry Andric ArgOffset = 68+4*NumAllocated; 547*0b57cec5SDimitry Andric } 548*0b57cec5SDimitry Andric 549*0b57cec5SDimitry Andric // Remember the vararg offset for the va_start implementation. 550*0b57cec5SDimitry Andric FuncInfo->setVarArgsFrameOffset(ArgOffset); 551*0b57cec5SDimitry Andric 552*0b57cec5SDimitry Andric std::vector<SDValue> OutChains; 553*0b57cec5SDimitry Andric 554*0b57cec5SDimitry Andric for (; CurArgReg != ArgRegEnd; ++CurArgReg) { 555*0b57cec5SDimitry Andric unsigned VReg = RegInfo.createVirtualRegister(&SP::IntRegsRegClass); 556*0b57cec5SDimitry Andric MF.getRegInfo().addLiveIn(*CurArgReg, VReg); 557*0b57cec5SDimitry Andric SDValue Arg = DAG.getCopyFromReg(DAG.getRoot(), dl, VReg, MVT::i32); 558*0b57cec5SDimitry Andric 559*0b57cec5SDimitry Andric int FrameIdx = MF.getFrameInfo().CreateFixedObject(4, ArgOffset, 560*0b57cec5SDimitry Andric true); 561*0b57cec5SDimitry Andric SDValue FIPtr = DAG.getFrameIndex(FrameIdx, MVT::i32); 562*0b57cec5SDimitry Andric 563*0b57cec5SDimitry Andric OutChains.push_back( 564*0b57cec5SDimitry Andric DAG.getStore(DAG.getRoot(), dl, Arg, FIPtr, MachinePointerInfo())); 565*0b57cec5SDimitry Andric ArgOffset += 4; 566*0b57cec5SDimitry Andric } 567*0b57cec5SDimitry Andric 568*0b57cec5SDimitry Andric if (!OutChains.empty()) { 569*0b57cec5SDimitry Andric OutChains.push_back(Chain); 570*0b57cec5SDimitry Andric Chain = DAG.getNode(ISD::TokenFactor, dl, MVT::Other, OutChains); 571*0b57cec5SDimitry Andric } 572*0b57cec5SDimitry Andric } 573*0b57cec5SDimitry Andric 574*0b57cec5SDimitry Andric return Chain; 575*0b57cec5SDimitry Andric } 576*0b57cec5SDimitry Andric 577*0b57cec5SDimitry Andric // Lower formal arguments for the 64 bit ABI. 578*0b57cec5SDimitry Andric SDValue SparcTargetLowering::LowerFormalArguments_64( 579*0b57cec5SDimitry Andric SDValue Chain, CallingConv::ID CallConv, bool IsVarArg, 580*0b57cec5SDimitry Andric const SmallVectorImpl<ISD::InputArg> &Ins, const SDLoc &DL, 581*0b57cec5SDimitry Andric SelectionDAG &DAG, SmallVectorImpl<SDValue> &InVals) const { 582*0b57cec5SDimitry Andric MachineFunction &MF = DAG.getMachineFunction(); 583*0b57cec5SDimitry Andric 584*0b57cec5SDimitry Andric // Analyze arguments according to CC_Sparc64. 585*0b57cec5SDimitry Andric SmallVector<CCValAssign, 16> ArgLocs; 586*0b57cec5SDimitry Andric CCState CCInfo(CallConv, IsVarArg, DAG.getMachineFunction(), ArgLocs, 587*0b57cec5SDimitry Andric *DAG.getContext()); 588*0b57cec5SDimitry Andric CCInfo.AnalyzeFormalArguments(Ins, CC_Sparc64); 589*0b57cec5SDimitry Andric 590*0b57cec5SDimitry Andric // The argument array begins at %fp+BIAS+128, after the register save area. 591*0b57cec5SDimitry Andric const unsigned ArgArea = 128; 592*0b57cec5SDimitry Andric 593*0b57cec5SDimitry Andric for (unsigned i = 0, e = ArgLocs.size(); i != e; ++i) { 594*0b57cec5SDimitry Andric CCValAssign &VA = ArgLocs[i]; 595*0b57cec5SDimitry Andric if (VA.isRegLoc()) { 596*0b57cec5SDimitry Andric // This argument is passed in a register. 597*0b57cec5SDimitry Andric // All integer register arguments are promoted by the caller to i64. 598*0b57cec5SDimitry Andric 599*0b57cec5SDimitry Andric // Create a virtual register for the promoted live-in value. 600*0b57cec5SDimitry Andric unsigned VReg = MF.addLiveIn(VA.getLocReg(), 601*0b57cec5SDimitry Andric getRegClassFor(VA.getLocVT())); 602*0b57cec5SDimitry Andric SDValue Arg = DAG.getCopyFromReg(Chain, DL, VReg, VA.getLocVT()); 603*0b57cec5SDimitry Andric 604*0b57cec5SDimitry Andric // Get the high bits for i32 struct elements. 605*0b57cec5SDimitry Andric if (VA.getValVT() == MVT::i32 && VA.needsCustom()) 606*0b57cec5SDimitry Andric Arg = DAG.getNode(ISD::SRL, DL, VA.getLocVT(), Arg, 607*0b57cec5SDimitry Andric DAG.getConstant(32, DL, MVT::i32)); 608*0b57cec5SDimitry Andric 609*0b57cec5SDimitry Andric // The caller promoted the argument, so insert an Assert?ext SDNode so we 610*0b57cec5SDimitry Andric // won't promote the value again in this function. 611*0b57cec5SDimitry Andric switch (VA.getLocInfo()) { 612*0b57cec5SDimitry Andric case CCValAssign::SExt: 613*0b57cec5SDimitry Andric Arg = DAG.getNode(ISD::AssertSext, DL, VA.getLocVT(), Arg, 614*0b57cec5SDimitry Andric DAG.getValueType(VA.getValVT())); 615*0b57cec5SDimitry Andric break; 616*0b57cec5SDimitry Andric case CCValAssign::ZExt: 617*0b57cec5SDimitry Andric Arg = DAG.getNode(ISD::AssertZext, DL, VA.getLocVT(), Arg, 618*0b57cec5SDimitry Andric DAG.getValueType(VA.getValVT())); 619*0b57cec5SDimitry Andric break; 620*0b57cec5SDimitry Andric default: 621*0b57cec5SDimitry Andric break; 622*0b57cec5SDimitry Andric } 623*0b57cec5SDimitry Andric 624*0b57cec5SDimitry Andric // Truncate the register down to the argument type. 625*0b57cec5SDimitry Andric if (VA.isExtInLoc()) 626*0b57cec5SDimitry Andric Arg = DAG.getNode(ISD::TRUNCATE, DL, VA.getValVT(), Arg); 627*0b57cec5SDimitry Andric 628*0b57cec5SDimitry Andric InVals.push_back(Arg); 629*0b57cec5SDimitry Andric continue; 630*0b57cec5SDimitry Andric } 631*0b57cec5SDimitry Andric 632*0b57cec5SDimitry Andric // The registers are exhausted. This argument was passed on the stack. 633*0b57cec5SDimitry Andric assert(VA.isMemLoc()); 634*0b57cec5SDimitry Andric // The CC_Sparc64_Full/Half functions compute stack offsets relative to the 635*0b57cec5SDimitry Andric // beginning of the arguments area at %fp+BIAS+128. 636*0b57cec5SDimitry Andric unsigned Offset = VA.getLocMemOffset() + ArgArea; 637*0b57cec5SDimitry Andric unsigned ValSize = VA.getValVT().getSizeInBits() / 8; 638*0b57cec5SDimitry Andric // Adjust offset for extended arguments, SPARC is big-endian. 639*0b57cec5SDimitry Andric // The caller will have written the full slot with extended bytes, but we 640*0b57cec5SDimitry Andric // prefer our own extending loads. 641*0b57cec5SDimitry Andric if (VA.isExtInLoc()) 642*0b57cec5SDimitry Andric Offset += 8 - ValSize; 643*0b57cec5SDimitry Andric int FI = MF.getFrameInfo().CreateFixedObject(ValSize, Offset, true); 644*0b57cec5SDimitry Andric InVals.push_back( 645*0b57cec5SDimitry Andric DAG.getLoad(VA.getValVT(), DL, Chain, 646*0b57cec5SDimitry Andric DAG.getFrameIndex(FI, getPointerTy(MF.getDataLayout())), 647*0b57cec5SDimitry Andric MachinePointerInfo::getFixedStack(MF, FI))); 648*0b57cec5SDimitry Andric } 649*0b57cec5SDimitry Andric 650*0b57cec5SDimitry Andric if (!IsVarArg) 651*0b57cec5SDimitry Andric return Chain; 652*0b57cec5SDimitry Andric 653*0b57cec5SDimitry Andric // This function takes variable arguments, some of which may have been passed 654*0b57cec5SDimitry Andric // in registers %i0-%i5. Variable floating point arguments are never passed 655*0b57cec5SDimitry Andric // in floating point registers. They go on %i0-%i5 or on the stack like 656*0b57cec5SDimitry Andric // integer arguments. 657*0b57cec5SDimitry Andric // 658*0b57cec5SDimitry Andric // The va_start intrinsic needs to know the offset to the first variable 659*0b57cec5SDimitry Andric // argument. 660*0b57cec5SDimitry Andric unsigned ArgOffset = CCInfo.getNextStackOffset(); 661*0b57cec5SDimitry Andric SparcMachineFunctionInfo *FuncInfo = MF.getInfo<SparcMachineFunctionInfo>(); 662*0b57cec5SDimitry Andric // Skip the 128 bytes of register save area. 663*0b57cec5SDimitry Andric FuncInfo->setVarArgsFrameOffset(ArgOffset + ArgArea + 664*0b57cec5SDimitry Andric Subtarget->getStackPointerBias()); 665*0b57cec5SDimitry Andric 666*0b57cec5SDimitry Andric // Save the variable arguments that were passed in registers. 667*0b57cec5SDimitry Andric // The caller is required to reserve stack space for 6 arguments regardless 668*0b57cec5SDimitry Andric // of how many arguments were actually passed. 669*0b57cec5SDimitry Andric SmallVector<SDValue, 8> OutChains; 670*0b57cec5SDimitry Andric for (; ArgOffset < 6*8; ArgOffset += 8) { 671*0b57cec5SDimitry Andric unsigned VReg = MF.addLiveIn(SP::I0 + ArgOffset/8, &SP::I64RegsRegClass); 672*0b57cec5SDimitry Andric SDValue VArg = DAG.getCopyFromReg(Chain, DL, VReg, MVT::i64); 673*0b57cec5SDimitry Andric int FI = MF.getFrameInfo().CreateFixedObject(8, ArgOffset + ArgArea, true); 674*0b57cec5SDimitry Andric auto PtrVT = getPointerTy(MF.getDataLayout()); 675*0b57cec5SDimitry Andric OutChains.push_back( 676*0b57cec5SDimitry Andric DAG.getStore(Chain, DL, VArg, DAG.getFrameIndex(FI, PtrVT), 677*0b57cec5SDimitry Andric MachinePointerInfo::getFixedStack(MF, FI))); 678*0b57cec5SDimitry Andric } 679*0b57cec5SDimitry Andric 680*0b57cec5SDimitry Andric if (!OutChains.empty()) 681*0b57cec5SDimitry Andric Chain = DAG.getNode(ISD::TokenFactor, DL, MVT::Other, OutChains); 682*0b57cec5SDimitry Andric 683*0b57cec5SDimitry Andric return Chain; 684*0b57cec5SDimitry Andric } 685*0b57cec5SDimitry Andric 686*0b57cec5SDimitry Andric SDValue 687*0b57cec5SDimitry Andric SparcTargetLowering::LowerCall(TargetLowering::CallLoweringInfo &CLI, 688*0b57cec5SDimitry Andric SmallVectorImpl<SDValue> &InVals) const { 689*0b57cec5SDimitry Andric if (Subtarget->is64Bit()) 690*0b57cec5SDimitry Andric return LowerCall_64(CLI, InVals); 691*0b57cec5SDimitry Andric return LowerCall_32(CLI, InVals); 692*0b57cec5SDimitry Andric } 693*0b57cec5SDimitry Andric 694*0b57cec5SDimitry Andric static bool hasReturnsTwiceAttr(SelectionDAG &DAG, SDValue Callee, 695*0b57cec5SDimitry Andric ImmutableCallSite CS) { 696*0b57cec5SDimitry Andric if (CS) 697*0b57cec5SDimitry Andric return CS.hasFnAttr(Attribute::ReturnsTwice); 698*0b57cec5SDimitry Andric 699*0b57cec5SDimitry Andric const Function *CalleeFn = nullptr; 700*0b57cec5SDimitry Andric if (GlobalAddressSDNode *G = dyn_cast<GlobalAddressSDNode>(Callee)) { 701*0b57cec5SDimitry Andric CalleeFn = dyn_cast<Function>(G->getGlobal()); 702*0b57cec5SDimitry Andric } else if (ExternalSymbolSDNode *E = 703*0b57cec5SDimitry Andric dyn_cast<ExternalSymbolSDNode>(Callee)) { 704*0b57cec5SDimitry Andric const Function &Fn = DAG.getMachineFunction().getFunction(); 705*0b57cec5SDimitry Andric const Module *M = Fn.getParent(); 706*0b57cec5SDimitry Andric const char *CalleeName = E->getSymbol(); 707*0b57cec5SDimitry Andric CalleeFn = M->getFunction(CalleeName); 708*0b57cec5SDimitry Andric } 709*0b57cec5SDimitry Andric 710*0b57cec5SDimitry Andric if (!CalleeFn) 711*0b57cec5SDimitry Andric return false; 712*0b57cec5SDimitry Andric return CalleeFn->hasFnAttribute(Attribute::ReturnsTwice); 713*0b57cec5SDimitry Andric } 714*0b57cec5SDimitry Andric 715*0b57cec5SDimitry Andric // Lower a call for the 32-bit ABI. 716*0b57cec5SDimitry Andric SDValue 717*0b57cec5SDimitry Andric SparcTargetLowering::LowerCall_32(TargetLowering::CallLoweringInfo &CLI, 718*0b57cec5SDimitry Andric SmallVectorImpl<SDValue> &InVals) const { 719*0b57cec5SDimitry Andric SelectionDAG &DAG = CLI.DAG; 720*0b57cec5SDimitry Andric SDLoc &dl = CLI.DL; 721*0b57cec5SDimitry Andric SmallVectorImpl<ISD::OutputArg> &Outs = CLI.Outs; 722*0b57cec5SDimitry Andric SmallVectorImpl<SDValue> &OutVals = CLI.OutVals; 723*0b57cec5SDimitry Andric SmallVectorImpl<ISD::InputArg> &Ins = CLI.Ins; 724*0b57cec5SDimitry Andric SDValue Chain = CLI.Chain; 725*0b57cec5SDimitry Andric SDValue Callee = CLI.Callee; 726*0b57cec5SDimitry Andric bool &isTailCall = CLI.IsTailCall; 727*0b57cec5SDimitry Andric CallingConv::ID CallConv = CLI.CallConv; 728*0b57cec5SDimitry Andric bool isVarArg = CLI.IsVarArg; 729*0b57cec5SDimitry Andric 730*0b57cec5SDimitry Andric // Sparc target does not yet support tail call optimization. 731*0b57cec5SDimitry Andric isTailCall = false; 732*0b57cec5SDimitry Andric 733*0b57cec5SDimitry Andric // Analyze operands of the call, assigning locations to each operand. 734*0b57cec5SDimitry Andric SmallVector<CCValAssign, 16> ArgLocs; 735*0b57cec5SDimitry Andric CCState CCInfo(CallConv, isVarArg, DAG.getMachineFunction(), ArgLocs, 736*0b57cec5SDimitry Andric *DAG.getContext()); 737*0b57cec5SDimitry Andric CCInfo.AnalyzeCallOperands(Outs, CC_Sparc32); 738*0b57cec5SDimitry Andric 739*0b57cec5SDimitry Andric // Get the size of the outgoing arguments stack space requirement. 740*0b57cec5SDimitry Andric unsigned ArgsSize = CCInfo.getNextStackOffset(); 741*0b57cec5SDimitry Andric 742*0b57cec5SDimitry Andric // Keep stack frames 8-byte aligned. 743*0b57cec5SDimitry Andric ArgsSize = (ArgsSize+7) & ~7; 744*0b57cec5SDimitry Andric 745*0b57cec5SDimitry Andric MachineFrameInfo &MFI = DAG.getMachineFunction().getFrameInfo(); 746*0b57cec5SDimitry Andric 747*0b57cec5SDimitry Andric // Create local copies for byval args. 748*0b57cec5SDimitry Andric SmallVector<SDValue, 8> ByValArgs; 749*0b57cec5SDimitry Andric for (unsigned i = 0, e = Outs.size(); i != e; ++i) { 750*0b57cec5SDimitry Andric ISD::ArgFlagsTy Flags = Outs[i].Flags; 751*0b57cec5SDimitry Andric if (!Flags.isByVal()) 752*0b57cec5SDimitry Andric continue; 753*0b57cec5SDimitry Andric 754*0b57cec5SDimitry Andric SDValue Arg = OutVals[i]; 755*0b57cec5SDimitry Andric unsigned Size = Flags.getByValSize(); 756*0b57cec5SDimitry Andric unsigned Align = Flags.getByValAlign(); 757*0b57cec5SDimitry Andric 758*0b57cec5SDimitry Andric if (Size > 0U) { 759*0b57cec5SDimitry Andric int FI = MFI.CreateStackObject(Size, Align, false); 760*0b57cec5SDimitry Andric SDValue FIPtr = DAG.getFrameIndex(FI, getPointerTy(DAG.getDataLayout())); 761*0b57cec5SDimitry Andric SDValue SizeNode = DAG.getConstant(Size, dl, MVT::i32); 762*0b57cec5SDimitry Andric 763*0b57cec5SDimitry Andric Chain = DAG.getMemcpy(Chain, dl, FIPtr, Arg, SizeNode, Align, 764*0b57cec5SDimitry Andric false, // isVolatile, 765*0b57cec5SDimitry Andric (Size <= 32), // AlwaysInline if size <= 32, 766*0b57cec5SDimitry Andric false, // isTailCall 767*0b57cec5SDimitry Andric MachinePointerInfo(), MachinePointerInfo()); 768*0b57cec5SDimitry Andric ByValArgs.push_back(FIPtr); 769*0b57cec5SDimitry Andric } 770*0b57cec5SDimitry Andric else { 771*0b57cec5SDimitry Andric SDValue nullVal; 772*0b57cec5SDimitry Andric ByValArgs.push_back(nullVal); 773*0b57cec5SDimitry Andric } 774*0b57cec5SDimitry Andric } 775*0b57cec5SDimitry Andric 776*0b57cec5SDimitry Andric Chain = DAG.getCALLSEQ_START(Chain, ArgsSize, 0, dl); 777*0b57cec5SDimitry Andric 778*0b57cec5SDimitry Andric SmallVector<std::pair<unsigned, SDValue>, 8> RegsToPass; 779*0b57cec5SDimitry Andric SmallVector<SDValue, 8> MemOpChains; 780*0b57cec5SDimitry Andric 781*0b57cec5SDimitry Andric const unsigned StackOffset = 92; 782*0b57cec5SDimitry Andric bool hasStructRetAttr = false; 783*0b57cec5SDimitry Andric unsigned SRetArgSize = 0; 784*0b57cec5SDimitry Andric // Walk the register/memloc assignments, inserting copies/loads. 785*0b57cec5SDimitry Andric for (unsigned i = 0, realArgIdx = 0, byvalArgIdx = 0, e = ArgLocs.size(); 786*0b57cec5SDimitry Andric i != e; 787*0b57cec5SDimitry Andric ++i, ++realArgIdx) { 788*0b57cec5SDimitry Andric CCValAssign &VA = ArgLocs[i]; 789*0b57cec5SDimitry Andric SDValue Arg = OutVals[realArgIdx]; 790*0b57cec5SDimitry Andric 791*0b57cec5SDimitry Andric ISD::ArgFlagsTy Flags = Outs[realArgIdx].Flags; 792*0b57cec5SDimitry Andric 793*0b57cec5SDimitry Andric // Use local copy if it is a byval arg. 794*0b57cec5SDimitry Andric if (Flags.isByVal()) { 795*0b57cec5SDimitry Andric Arg = ByValArgs[byvalArgIdx++]; 796*0b57cec5SDimitry Andric if (!Arg) { 797*0b57cec5SDimitry Andric continue; 798*0b57cec5SDimitry Andric } 799*0b57cec5SDimitry Andric } 800*0b57cec5SDimitry Andric 801*0b57cec5SDimitry Andric // Promote the value if needed. 802*0b57cec5SDimitry Andric switch (VA.getLocInfo()) { 803*0b57cec5SDimitry Andric default: llvm_unreachable("Unknown loc info!"); 804*0b57cec5SDimitry Andric case CCValAssign::Full: break; 805*0b57cec5SDimitry Andric case CCValAssign::SExt: 806*0b57cec5SDimitry Andric Arg = DAG.getNode(ISD::SIGN_EXTEND, dl, VA.getLocVT(), Arg); 807*0b57cec5SDimitry Andric break; 808*0b57cec5SDimitry Andric case CCValAssign::ZExt: 809*0b57cec5SDimitry Andric Arg = DAG.getNode(ISD::ZERO_EXTEND, dl, VA.getLocVT(), Arg); 810*0b57cec5SDimitry Andric break; 811*0b57cec5SDimitry Andric case CCValAssign::AExt: 812*0b57cec5SDimitry Andric Arg = DAG.getNode(ISD::ANY_EXTEND, dl, VA.getLocVT(), Arg); 813*0b57cec5SDimitry Andric break; 814*0b57cec5SDimitry Andric case CCValAssign::BCvt: 815*0b57cec5SDimitry Andric Arg = DAG.getNode(ISD::BITCAST, dl, VA.getLocVT(), Arg); 816*0b57cec5SDimitry Andric break; 817*0b57cec5SDimitry Andric } 818*0b57cec5SDimitry Andric 819*0b57cec5SDimitry Andric if (Flags.isSRet()) { 820*0b57cec5SDimitry Andric assert(VA.needsCustom()); 821*0b57cec5SDimitry Andric // store SRet argument in %sp+64 822*0b57cec5SDimitry Andric SDValue StackPtr = DAG.getRegister(SP::O6, MVT::i32); 823*0b57cec5SDimitry Andric SDValue PtrOff = DAG.getIntPtrConstant(64, dl); 824*0b57cec5SDimitry Andric PtrOff = DAG.getNode(ISD::ADD, dl, MVT::i32, StackPtr, PtrOff); 825*0b57cec5SDimitry Andric MemOpChains.push_back( 826*0b57cec5SDimitry Andric DAG.getStore(Chain, dl, Arg, PtrOff, MachinePointerInfo())); 827*0b57cec5SDimitry Andric hasStructRetAttr = true; 828*0b57cec5SDimitry Andric // sret only allowed on first argument 829*0b57cec5SDimitry Andric assert(Outs[realArgIdx].OrigArgIndex == 0); 830*0b57cec5SDimitry Andric PointerType *Ty = cast<PointerType>(CLI.getArgs()[0].Ty); 831*0b57cec5SDimitry Andric Type *ElementTy = Ty->getElementType(); 832*0b57cec5SDimitry Andric SRetArgSize = DAG.getDataLayout().getTypeAllocSize(ElementTy); 833*0b57cec5SDimitry Andric continue; 834*0b57cec5SDimitry Andric } 835*0b57cec5SDimitry Andric 836*0b57cec5SDimitry Andric if (VA.needsCustom()) { 837*0b57cec5SDimitry Andric assert(VA.getLocVT() == MVT::f64 || VA.getLocVT() == MVT::v2i32); 838*0b57cec5SDimitry Andric 839*0b57cec5SDimitry Andric if (VA.isMemLoc()) { 840*0b57cec5SDimitry Andric unsigned Offset = VA.getLocMemOffset() + StackOffset; 841*0b57cec5SDimitry Andric // if it is double-word aligned, just store. 842*0b57cec5SDimitry Andric if (Offset % 8 == 0) { 843*0b57cec5SDimitry Andric SDValue StackPtr = DAG.getRegister(SP::O6, MVT::i32); 844*0b57cec5SDimitry Andric SDValue PtrOff = DAG.getIntPtrConstant(Offset, dl); 845*0b57cec5SDimitry Andric PtrOff = DAG.getNode(ISD::ADD, dl, MVT::i32, StackPtr, PtrOff); 846*0b57cec5SDimitry Andric MemOpChains.push_back( 847*0b57cec5SDimitry Andric DAG.getStore(Chain, dl, Arg, PtrOff, MachinePointerInfo())); 848*0b57cec5SDimitry Andric continue; 849*0b57cec5SDimitry Andric } 850*0b57cec5SDimitry Andric } 851*0b57cec5SDimitry Andric 852*0b57cec5SDimitry Andric if (VA.getLocVT() == MVT::f64) { 853*0b57cec5SDimitry Andric // Move from the float value from float registers into the 854*0b57cec5SDimitry Andric // integer registers. 855*0b57cec5SDimitry Andric if (ConstantFPSDNode *C = dyn_cast<ConstantFPSDNode>(Arg)) 856*0b57cec5SDimitry Andric Arg = bitcastConstantFPToInt(C, dl, DAG); 857*0b57cec5SDimitry Andric else 858*0b57cec5SDimitry Andric Arg = DAG.getNode(ISD::BITCAST, dl, MVT::v2i32, Arg); 859*0b57cec5SDimitry Andric } 860*0b57cec5SDimitry Andric 861*0b57cec5SDimitry Andric SDValue Part0 = DAG.getNode(ISD::EXTRACT_VECTOR_ELT, dl, MVT::i32, 862*0b57cec5SDimitry Andric Arg, 863*0b57cec5SDimitry Andric DAG.getConstant(0, dl, getVectorIdxTy(DAG.getDataLayout()))); 864*0b57cec5SDimitry Andric SDValue Part1 = DAG.getNode(ISD::EXTRACT_VECTOR_ELT, dl, MVT::i32, 865*0b57cec5SDimitry Andric Arg, 866*0b57cec5SDimitry Andric DAG.getConstant(1, dl, getVectorIdxTy(DAG.getDataLayout()))); 867*0b57cec5SDimitry Andric 868*0b57cec5SDimitry Andric if (VA.isRegLoc()) { 869*0b57cec5SDimitry Andric RegsToPass.push_back(std::make_pair(VA.getLocReg(), Part0)); 870*0b57cec5SDimitry Andric assert(i+1 != e); 871*0b57cec5SDimitry Andric CCValAssign &NextVA = ArgLocs[++i]; 872*0b57cec5SDimitry Andric if (NextVA.isRegLoc()) { 873*0b57cec5SDimitry Andric RegsToPass.push_back(std::make_pair(NextVA.getLocReg(), Part1)); 874*0b57cec5SDimitry Andric } else { 875*0b57cec5SDimitry Andric // Store the second part in stack. 876*0b57cec5SDimitry Andric unsigned Offset = NextVA.getLocMemOffset() + StackOffset; 877*0b57cec5SDimitry Andric SDValue StackPtr = DAG.getRegister(SP::O6, MVT::i32); 878*0b57cec5SDimitry Andric SDValue PtrOff = DAG.getIntPtrConstant(Offset, dl); 879*0b57cec5SDimitry Andric PtrOff = DAG.getNode(ISD::ADD, dl, MVT::i32, StackPtr, PtrOff); 880*0b57cec5SDimitry Andric MemOpChains.push_back( 881*0b57cec5SDimitry Andric DAG.getStore(Chain, dl, Part1, PtrOff, MachinePointerInfo())); 882*0b57cec5SDimitry Andric } 883*0b57cec5SDimitry Andric } else { 884*0b57cec5SDimitry Andric unsigned Offset = VA.getLocMemOffset() + StackOffset; 885*0b57cec5SDimitry Andric // Store the first part. 886*0b57cec5SDimitry Andric SDValue StackPtr = DAG.getRegister(SP::O6, MVT::i32); 887*0b57cec5SDimitry Andric SDValue PtrOff = DAG.getIntPtrConstant(Offset, dl); 888*0b57cec5SDimitry Andric PtrOff = DAG.getNode(ISD::ADD, dl, MVT::i32, StackPtr, PtrOff); 889*0b57cec5SDimitry Andric MemOpChains.push_back( 890*0b57cec5SDimitry Andric DAG.getStore(Chain, dl, Part0, PtrOff, MachinePointerInfo())); 891*0b57cec5SDimitry Andric // Store the second part. 892*0b57cec5SDimitry Andric PtrOff = DAG.getIntPtrConstant(Offset + 4, dl); 893*0b57cec5SDimitry Andric PtrOff = DAG.getNode(ISD::ADD, dl, MVT::i32, StackPtr, PtrOff); 894*0b57cec5SDimitry Andric MemOpChains.push_back( 895*0b57cec5SDimitry Andric DAG.getStore(Chain, dl, Part1, PtrOff, MachinePointerInfo())); 896*0b57cec5SDimitry Andric } 897*0b57cec5SDimitry Andric continue; 898*0b57cec5SDimitry Andric } 899*0b57cec5SDimitry Andric 900*0b57cec5SDimitry Andric // Arguments that can be passed on register must be kept at 901*0b57cec5SDimitry Andric // RegsToPass vector 902*0b57cec5SDimitry Andric if (VA.isRegLoc()) { 903*0b57cec5SDimitry Andric if (VA.getLocVT() != MVT::f32) { 904*0b57cec5SDimitry Andric RegsToPass.push_back(std::make_pair(VA.getLocReg(), Arg)); 905*0b57cec5SDimitry Andric continue; 906*0b57cec5SDimitry Andric } 907*0b57cec5SDimitry Andric Arg = DAG.getNode(ISD::BITCAST, dl, MVT::i32, Arg); 908*0b57cec5SDimitry Andric RegsToPass.push_back(std::make_pair(VA.getLocReg(), Arg)); 909*0b57cec5SDimitry Andric continue; 910*0b57cec5SDimitry Andric } 911*0b57cec5SDimitry Andric 912*0b57cec5SDimitry Andric assert(VA.isMemLoc()); 913*0b57cec5SDimitry Andric 914*0b57cec5SDimitry Andric // Create a store off the stack pointer for this argument. 915*0b57cec5SDimitry Andric SDValue StackPtr = DAG.getRegister(SP::O6, MVT::i32); 916*0b57cec5SDimitry Andric SDValue PtrOff = DAG.getIntPtrConstant(VA.getLocMemOffset() + StackOffset, 917*0b57cec5SDimitry Andric dl); 918*0b57cec5SDimitry Andric PtrOff = DAG.getNode(ISD::ADD, dl, MVT::i32, StackPtr, PtrOff); 919*0b57cec5SDimitry Andric MemOpChains.push_back( 920*0b57cec5SDimitry Andric DAG.getStore(Chain, dl, Arg, PtrOff, MachinePointerInfo())); 921*0b57cec5SDimitry Andric } 922*0b57cec5SDimitry Andric 923*0b57cec5SDimitry Andric 924*0b57cec5SDimitry Andric // Emit all stores, make sure the occur before any copies into physregs. 925*0b57cec5SDimitry Andric if (!MemOpChains.empty()) 926*0b57cec5SDimitry Andric Chain = DAG.getNode(ISD::TokenFactor, dl, MVT::Other, MemOpChains); 927*0b57cec5SDimitry Andric 928*0b57cec5SDimitry Andric // Build a sequence of copy-to-reg nodes chained together with token 929*0b57cec5SDimitry Andric // chain and flag operands which copy the outgoing args into registers. 930*0b57cec5SDimitry Andric // The InFlag in necessary since all emitted instructions must be 931*0b57cec5SDimitry Andric // stuck together. 932*0b57cec5SDimitry Andric SDValue InFlag; 933*0b57cec5SDimitry Andric for (unsigned i = 0, e = RegsToPass.size(); i != e; ++i) { 934*0b57cec5SDimitry Andric unsigned Reg = toCallerWindow(RegsToPass[i].first); 935*0b57cec5SDimitry Andric Chain = DAG.getCopyToReg(Chain, dl, Reg, RegsToPass[i].second, InFlag); 936*0b57cec5SDimitry Andric InFlag = Chain.getValue(1); 937*0b57cec5SDimitry Andric } 938*0b57cec5SDimitry Andric 939*0b57cec5SDimitry Andric bool hasReturnsTwice = hasReturnsTwiceAttr(DAG, Callee, CLI.CS); 940*0b57cec5SDimitry Andric 941*0b57cec5SDimitry Andric // If the callee is a GlobalAddress node (quite common, every direct call is) 942*0b57cec5SDimitry Andric // turn it into a TargetGlobalAddress node so that legalize doesn't hack it. 943*0b57cec5SDimitry Andric // Likewise ExternalSymbol -> TargetExternalSymbol. 944*0b57cec5SDimitry Andric unsigned TF = isPositionIndependent() ? SparcMCExpr::VK_Sparc_WPLT30 : 0; 945*0b57cec5SDimitry Andric if (GlobalAddressSDNode *G = dyn_cast<GlobalAddressSDNode>(Callee)) 946*0b57cec5SDimitry Andric Callee = DAG.getTargetGlobalAddress(G->getGlobal(), dl, MVT::i32, 0, TF); 947*0b57cec5SDimitry Andric else if (ExternalSymbolSDNode *E = dyn_cast<ExternalSymbolSDNode>(Callee)) 948*0b57cec5SDimitry Andric Callee = DAG.getTargetExternalSymbol(E->getSymbol(), MVT::i32, TF); 949*0b57cec5SDimitry Andric 950*0b57cec5SDimitry Andric // Returns a chain & a flag for retval copy to use 951*0b57cec5SDimitry Andric SDVTList NodeTys = DAG.getVTList(MVT::Other, MVT::Glue); 952*0b57cec5SDimitry Andric SmallVector<SDValue, 8> Ops; 953*0b57cec5SDimitry Andric Ops.push_back(Chain); 954*0b57cec5SDimitry Andric Ops.push_back(Callee); 955*0b57cec5SDimitry Andric if (hasStructRetAttr) 956*0b57cec5SDimitry Andric Ops.push_back(DAG.getTargetConstant(SRetArgSize, dl, MVT::i32)); 957*0b57cec5SDimitry Andric for (unsigned i = 0, e = RegsToPass.size(); i != e; ++i) 958*0b57cec5SDimitry Andric Ops.push_back(DAG.getRegister(toCallerWindow(RegsToPass[i].first), 959*0b57cec5SDimitry Andric RegsToPass[i].second.getValueType())); 960*0b57cec5SDimitry Andric 961*0b57cec5SDimitry Andric // Add a register mask operand representing the call-preserved registers. 962*0b57cec5SDimitry Andric const SparcRegisterInfo *TRI = Subtarget->getRegisterInfo(); 963*0b57cec5SDimitry Andric const uint32_t *Mask = 964*0b57cec5SDimitry Andric ((hasReturnsTwice) 965*0b57cec5SDimitry Andric ? TRI->getRTCallPreservedMask(CallConv) 966*0b57cec5SDimitry Andric : TRI->getCallPreservedMask(DAG.getMachineFunction(), CallConv)); 967*0b57cec5SDimitry Andric assert(Mask && "Missing call preserved mask for calling convention"); 968*0b57cec5SDimitry Andric Ops.push_back(DAG.getRegisterMask(Mask)); 969*0b57cec5SDimitry Andric 970*0b57cec5SDimitry Andric if (InFlag.getNode()) 971*0b57cec5SDimitry Andric Ops.push_back(InFlag); 972*0b57cec5SDimitry Andric 973*0b57cec5SDimitry Andric Chain = DAG.getNode(SPISD::CALL, dl, NodeTys, Ops); 974*0b57cec5SDimitry Andric InFlag = Chain.getValue(1); 975*0b57cec5SDimitry Andric 976*0b57cec5SDimitry Andric Chain = DAG.getCALLSEQ_END(Chain, DAG.getIntPtrConstant(ArgsSize, dl, true), 977*0b57cec5SDimitry Andric DAG.getIntPtrConstant(0, dl, true), InFlag, dl); 978*0b57cec5SDimitry Andric InFlag = Chain.getValue(1); 979*0b57cec5SDimitry Andric 980*0b57cec5SDimitry Andric // Assign locations to each value returned by this call. 981*0b57cec5SDimitry Andric SmallVector<CCValAssign, 16> RVLocs; 982*0b57cec5SDimitry Andric CCState RVInfo(CallConv, isVarArg, DAG.getMachineFunction(), RVLocs, 983*0b57cec5SDimitry Andric *DAG.getContext()); 984*0b57cec5SDimitry Andric 985*0b57cec5SDimitry Andric RVInfo.AnalyzeCallResult(Ins, RetCC_Sparc32); 986*0b57cec5SDimitry Andric 987*0b57cec5SDimitry Andric // Copy all of the result registers out of their specified physreg. 988*0b57cec5SDimitry Andric for (unsigned i = 0; i != RVLocs.size(); ++i) { 989*0b57cec5SDimitry Andric if (RVLocs[i].getLocVT() == MVT::v2i32) { 990*0b57cec5SDimitry Andric SDValue Vec = DAG.getNode(ISD::UNDEF, dl, MVT::v2i32); 991*0b57cec5SDimitry Andric SDValue Lo = DAG.getCopyFromReg( 992*0b57cec5SDimitry Andric Chain, dl, toCallerWindow(RVLocs[i++].getLocReg()), MVT::i32, InFlag); 993*0b57cec5SDimitry Andric Chain = Lo.getValue(1); 994*0b57cec5SDimitry Andric InFlag = Lo.getValue(2); 995*0b57cec5SDimitry Andric Vec = DAG.getNode(ISD::INSERT_VECTOR_ELT, dl, MVT::v2i32, Vec, Lo, 996*0b57cec5SDimitry Andric DAG.getConstant(0, dl, MVT::i32)); 997*0b57cec5SDimitry Andric SDValue Hi = DAG.getCopyFromReg( 998*0b57cec5SDimitry Andric Chain, dl, toCallerWindow(RVLocs[i].getLocReg()), MVT::i32, InFlag); 999*0b57cec5SDimitry Andric Chain = Hi.getValue(1); 1000*0b57cec5SDimitry Andric InFlag = Hi.getValue(2); 1001*0b57cec5SDimitry Andric Vec = DAG.getNode(ISD::INSERT_VECTOR_ELT, dl, MVT::v2i32, Vec, Hi, 1002*0b57cec5SDimitry Andric DAG.getConstant(1, dl, MVT::i32)); 1003*0b57cec5SDimitry Andric InVals.push_back(Vec); 1004*0b57cec5SDimitry Andric } else { 1005*0b57cec5SDimitry Andric Chain = 1006*0b57cec5SDimitry Andric DAG.getCopyFromReg(Chain, dl, toCallerWindow(RVLocs[i].getLocReg()), 1007*0b57cec5SDimitry Andric RVLocs[i].getValVT(), InFlag) 1008*0b57cec5SDimitry Andric .getValue(1); 1009*0b57cec5SDimitry Andric InFlag = Chain.getValue(2); 1010*0b57cec5SDimitry Andric InVals.push_back(Chain.getValue(0)); 1011*0b57cec5SDimitry Andric } 1012*0b57cec5SDimitry Andric } 1013*0b57cec5SDimitry Andric 1014*0b57cec5SDimitry Andric return Chain; 1015*0b57cec5SDimitry Andric } 1016*0b57cec5SDimitry Andric 1017*0b57cec5SDimitry Andric // FIXME? Maybe this could be a TableGen attribute on some registers and 1018*0b57cec5SDimitry Andric // this table could be generated automatically from RegInfo. 1019*0b57cec5SDimitry Andric unsigned SparcTargetLowering::getRegisterByName(const char* RegName, EVT VT, 1020*0b57cec5SDimitry Andric SelectionDAG &DAG) const { 1021*0b57cec5SDimitry Andric unsigned Reg = StringSwitch<unsigned>(RegName) 1022*0b57cec5SDimitry Andric .Case("i0", SP::I0).Case("i1", SP::I1).Case("i2", SP::I2).Case("i3", SP::I3) 1023*0b57cec5SDimitry Andric .Case("i4", SP::I4).Case("i5", SP::I5).Case("i6", SP::I6).Case("i7", SP::I7) 1024*0b57cec5SDimitry Andric .Case("o0", SP::O0).Case("o1", SP::O1).Case("o2", SP::O2).Case("o3", SP::O3) 1025*0b57cec5SDimitry Andric .Case("o4", SP::O4).Case("o5", SP::O5).Case("o6", SP::O6).Case("o7", SP::O7) 1026*0b57cec5SDimitry Andric .Case("l0", SP::L0).Case("l1", SP::L1).Case("l2", SP::L2).Case("l3", SP::L3) 1027*0b57cec5SDimitry Andric .Case("l4", SP::L4).Case("l5", SP::L5).Case("l6", SP::L6).Case("l7", SP::L7) 1028*0b57cec5SDimitry Andric .Case("g0", SP::G0).Case("g1", SP::G1).Case("g2", SP::G2).Case("g3", SP::G3) 1029*0b57cec5SDimitry Andric .Case("g4", SP::G4).Case("g5", SP::G5).Case("g6", SP::G6).Case("g7", SP::G7) 1030*0b57cec5SDimitry Andric .Default(0); 1031*0b57cec5SDimitry Andric 1032*0b57cec5SDimitry Andric if (Reg) 1033*0b57cec5SDimitry Andric return Reg; 1034*0b57cec5SDimitry Andric 1035*0b57cec5SDimitry Andric report_fatal_error("Invalid register name global variable"); 1036*0b57cec5SDimitry Andric } 1037*0b57cec5SDimitry Andric 1038*0b57cec5SDimitry Andric // Fixup floating point arguments in the ... part of a varargs call. 1039*0b57cec5SDimitry Andric // 1040*0b57cec5SDimitry Andric // The SPARC v9 ABI requires that floating point arguments are treated the same 1041*0b57cec5SDimitry Andric // as integers when calling a varargs function. This does not apply to the 1042*0b57cec5SDimitry Andric // fixed arguments that are part of the function's prototype. 1043*0b57cec5SDimitry Andric // 1044*0b57cec5SDimitry Andric // This function post-processes a CCValAssign array created by 1045*0b57cec5SDimitry Andric // AnalyzeCallOperands(). 1046*0b57cec5SDimitry Andric static void fixupVariableFloatArgs(SmallVectorImpl<CCValAssign> &ArgLocs, 1047*0b57cec5SDimitry Andric ArrayRef<ISD::OutputArg> Outs) { 1048*0b57cec5SDimitry Andric for (unsigned i = 0, e = ArgLocs.size(); i != e; ++i) { 1049*0b57cec5SDimitry Andric const CCValAssign &VA = ArgLocs[i]; 1050*0b57cec5SDimitry Andric MVT ValTy = VA.getLocVT(); 1051*0b57cec5SDimitry Andric // FIXME: What about f32 arguments? C promotes them to f64 when calling 1052*0b57cec5SDimitry Andric // varargs functions. 1053*0b57cec5SDimitry Andric if (!VA.isRegLoc() || (ValTy != MVT::f64 && ValTy != MVT::f128)) 1054*0b57cec5SDimitry Andric continue; 1055*0b57cec5SDimitry Andric // The fixed arguments to a varargs function still go in FP registers. 1056*0b57cec5SDimitry Andric if (Outs[VA.getValNo()].IsFixed) 1057*0b57cec5SDimitry Andric continue; 1058*0b57cec5SDimitry Andric 1059*0b57cec5SDimitry Andric // This floating point argument should be reassigned. 1060*0b57cec5SDimitry Andric CCValAssign NewVA; 1061*0b57cec5SDimitry Andric 1062*0b57cec5SDimitry Andric // Determine the offset into the argument array. 1063*0b57cec5SDimitry Andric unsigned firstReg = (ValTy == MVT::f64) ? SP::D0 : SP::Q0; 1064*0b57cec5SDimitry Andric unsigned argSize = (ValTy == MVT::f64) ? 8 : 16; 1065*0b57cec5SDimitry Andric unsigned Offset = argSize * (VA.getLocReg() - firstReg); 1066*0b57cec5SDimitry Andric assert(Offset < 16*8 && "Offset out of range, bad register enum?"); 1067*0b57cec5SDimitry Andric 1068*0b57cec5SDimitry Andric if (Offset < 6*8) { 1069*0b57cec5SDimitry Andric // This argument should go in %i0-%i5. 1070*0b57cec5SDimitry Andric unsigned IReg = SP::I0 + Offset/8; 1071*0b57cec5SDimitry Andric if (ValTy == MVT::f64) 1072*0b57cec5SDimitry Andric // Full register, just bitconvert into i64. 1073*0b57cec5SDimitry Andric NewVA = CCValAssign::getReg(VA.getValNo(), VA.getValVT(), 1074*0b57cec5SDimitry Andric IReg, MVT::i64, CCValAssign::BCvt); 1075*0b57cec5SDimitry Andric else { 1076*0b57cec5SDimitry Andric assert(ValTy == MVT::f128 && "Unexpected type!"); 1077*0b57cec5SDimitry Andric // Full register, just bitconvert into i128 -- We will lower this into 1078*0b57cec5SDimitry Andric // two i64s in LowerCall_64. 1079*0b57cec5SDimitry Andric NewVA = CCValAssign::getCustomReg(VA.getValNo(), VA.getValVT(), 1080*0b57cec5SDimitry Andric IReg, MVT::i128, CCValAssign::BCvt); 1081*0b57cec5SDimitry Andric } 1082*0b57cec5SDimitry Andric } else { 1083*0b57cec5SDimitry Andric // This needs to go to memory, we're out of integer registers. 1084*0b57cec5SDimitry Andric NewVA = CCValAssign::getMem(VA.getValNo(), VA.getValVT(), 1085*0b57cec5SDimitry Andric Offset, VA.getLocVT(), VA.getLocInfo()); 1086*0b57cec5SDimitry Andric } 1087*0b57cec5SDimitry Andric ArgLocs[i] = NewVA; 1088*0b57cec5SDimitry Andric } 1089*0b57cec5SDimitry Andric } 1090*0b57cec5SDimitry Andric 1091*0b57cec5SDimitry Andric // Lower a call for the 64-bit ABI. 1092*0b57cec5SDimitry Andric SDValue 1093*0b57cec5SDimitry Andric SparcTargetLowering::LowerCall_64(TargetLowering::CallLoweringInfo &CLI, 1094*0b57cec5SDimitry Andric SmallVectorImpl<SDValue> &InVals) const { 1095*0b57cec5SDimitry Andric SelectionDAG &DAG = CLI.DAG; 1096*0b57cec5SDimitry Andric SDLoc DL = CLI.DL; 1097*0b57cec5SDimitry Andric SDValue Chain = CLI.Chain; 1098*0b57cec5SDimitry Andric auto PtrVT = getPointerTy(DAG.getDataLayout()); 1099*0b57cec5SDimitry Andric 1100*0b57cec5SDimitry Andric // Sparc target does not yet support tail call optimization. 1101*0b57cec5SDimitry Andric CLI.IsTailCall = false; 1102*0b57cec5SDimitry Andric 1103*0b57cec5SDimitry Andric // Analyze operands of the call, assigning locations to each operand. 1104*0b57cec5SDimitry Andric SmallVector<CCValAssign, 16> ArgLocs; 1105*0b57cec5SDimitry Andric CCState CCInfo(CLI.CallConv, CLI.IsVarArg, DAG.getMachineFunction(), ArgLocs, 1106*0b57cec5SDimitry Andric *DAG.getContext()); 1107*0b57cec5SDimitry Andric CCInfo.AnalyzeCallOperands(CLI.Outs, CC_Sparc64); 1108*0b57cec5SDimitry Andric 1109*0b57cec5SDimitry Andric // Get the size of the outgoing arguments stack space requirement. 1110*0b57cec5SDimitry Andric // The stack offset computed by CC_Sparc64 includes all arguments. 1111*0b57cec5SDimitry Andric // Called functions expect 6 argument words to exist in the stack frame, used 1112*0b57cec5SDimitry Andric // or not. 1113*0b57cec5SDimitry Andric unsigned ArgsSize = std::max(6*8u, CCInfo.getNextStackOffset()); 1114*0b57cec5SDimitry Andric 1115*0b57cec5SDimitry Andric // Keep stack frames 16-byte aligned. 1116*0b57cec5SDimitry Andric ArgsSize = alignTo(ArgsSize, 16); 1117*0b57cec5SDimitry Andric 1118*0b57cec5SDimitry Andric // Varargs calls require special treatment. 1119*0b57cec5SDimitry Andric if (CLI.IsVarArg) 1120*0b57cec5SDimitry Andric fixupVariableFloatArgs(ArgLocs, CLI.Outs); 1121*0b57cec5SDimitry Andric 1122*0b57cec5SDimitry Andric // Adjust the stack pointer to make room for the arguments. 1123*0b57cec5SDimitry Andric // FIXME: Use hasReservedCallFrame to avoid %sp adjustments around all calls 1124*0b57cec5SDimitry Andric // with more than 6 arguments. 1125*0b57cec5SDimitry Andric Chain = DAG.getCALLSEQ_START(Chain, ArgsSize, 0, DL); 1126*0b57cec5SDimitry Andric 1127*0b57cec5SDimitry Andric // Collect the set of registers to pass to the function and their values. 1128*0b57cec5SDimitry Andric // This will be emitted as a sequence of CopyToReg nodes glued to the call 1129*0b57cec5SDimitry Andric // instruction. 1130*0b57cec5SDimitry Andric SmallVector<std::pair<unsigned, SDValue>, 8> RegsToPass; 1131*0b57cec5SDimitry Andric 1132*0b57cec5SDimitry Andric // Collect chains from all the memory opeations that copy arguments to the 1133*0b57cec5SDimitry Andric // stack. They must follow the stack pointer adjustment above and precede the 1134*0b57cec5SDimitry Andric // call instruction itself. 1135*0b57cec5SDimitry Andric SmallVector<SDValue, 8> MemOpChains; 1136*0b57cec5SDimitry Andric 1137*0b57cec5SDimitry Andric for (unsigned i = 0, e = ArgLocs.size(); i != e; ++i) { 1138*0b57cec5SDimitry Andric const CCValAssign &VA = ArgLocs[i]; 1139*0b57cec5SDimitry Andric SDValue Arg = CLI.OutVals[i]; 1140*0b57cec5SDimitry Andric 1141*0b57cec5SDimitry Andric // Promote the value if needed. 1142*0b57cec5SDimitry Andric switch (VA.getLocInfo()) { 1143*0b57cec5SDimitry Andric default: 1144*0b57cec5SDimitry Andric llvm_unreachable("Unknown location info!"); 1145*0b57cec5SDimitry Andric case CCValAssign::Full: 1146*0b57cec5SDimitry Andric break; 1147*0b57cec5SDimitry Andric case CCValAssign::SExt: 1148*0b57cec5SDimitry Andric Arg = DAG.getNode(ISD::SIGN_EXTEND, DL, VA.getLocVT(), Arg); 1149*0b57cec5SDimitry Andric break; 1150*0b57cec5SDimitry Andric case CCValAssign::ZExt: 1151*0b57cec5SDimitry Andric Arg = DAG.getNode(ISD::ZERO_EXTEND, DL, VA.getLocVT(), Arg); 1152*0b57cec5SDimitry Andric break; 1153*0b57cec5SDimitry Andric case CCValAssign::AExt: 1154*0b57cec5SDimitry Andric Arg = DAG.getNode(ISD::ANY_EXTEND, DL, VA.getLocVT(), Arg); 1155*0b57cec5SDimitry Andric break; 1156*0b57cec5SDimitry Andric case CCValAssign::BCvt: 1157*0b57cec5SDimitry Andric // fixupVariableFloatArgs() may create bitcasts from f128 to i128. But 1158*0b57cec5SDimitry Andric // SPARC does not support i128 natively. Lower it into two i64, see below. 1159*0b57cec5SDimitry Andric if (!VA.needsCustom() || VA.getValVT() != MVT::f128 1160*0b57cec5SDimitry Andric || VA.getLocVT() != MVT::i128) 1161*0b57cec5SDimitry Andric Arg = DAG.getNode(ISD::BITCAST, DL, VA.getLocVT(), Arg); 1162*0b57cec5SDimitry Andric break; 1163*0b57cec5SDimitry Andric } 1164*0b57cec5SDimitry Andric 1165*0b57cec5SDimitry Andric if (VA.isRegLoc()) { 1166*0b57cec5SDimitry Andric if (VA.needsCustom() && VA.getValVT() == MVT::f128 1167*0b57cec5SDimitry Andric && VA.getLocVT() == MVT::i128) { 1168*0b57cec5SDimitry Andric // Store and reload into the integer register reg and reg+1. 1169*0b57cec5SDimitry Andric unsigned Offset = 8 * (VA.getLocReg() - SP::I0); 1170*0b57cec5SDimitry Andric unsigned StackOffset = Offset + Subtarget->getStackPointerBias() + 128; 1171*0b57cec5SDimitry Andric SDValue StackPtr = DAG.getRegister(SP::O6, PtrVT); 1172*0b57cec5SDimitry Andric SDValue HiPtrOff = DAG.getIntPtrConstant(StackOffset, DL); 1173*0b57cec5SDimitry Andric HiPtrOff = DAG.getNode(ISD::ADD, DL, PtrVT, StackPtr, HiPtrOff); 1174*0b57cec5SDimitry Andric SDValue LoPtrOff = DAG.getIntPtrConstant(StackOffset + 8, DL); 1175*0b57cec5SDimitry Andric LoPtrOff = DAG.getNode(ISD::ADD, DL, PtrVT, StackPtr, LoPtrOff); 1176*0b57cec5SDimitry Andric 1177*0b57cec5SDimitry Andric // Store to %sp+BIAS+128+Offset 1178*0b57cec5SDimitry Andric SDValue Store = 1179*0b57cec5SDimitry Andric DAG.getStore(Chain, DL, Arg, HiPtrOff, MachinePointerInfo()); 1180*0b57cec5SDimitry Andric // Load into Reg and Reg+1 1181*0b57cec5SDimitry Andric SDValue Hi64 = 1182*0b57cec5SDimitry Andric DAG.getLoad(MVT::i64, DL, Store, HiPtrOff, MachinePointerInfo()); 1183*0b57cec5SDimitry Andric SDValue Lo64 = 1184*0b57cec5SDimitry Andric DAG.getLoad(MVT::i64, DL, Store, LoPtrOff, MachinePointerInfo()); 1185*0b57cec5SDimitry Andric RegsToPass.push_back(std::make_pair(toCallerWindow(VA.getLocReg()), 1186*0b57cec5SDimitry Andric Hi64)); 1187*0b57cec5SDimitry Andric RegsToPass.push_back(std::make_pair(toCallerWindow(VA.getLocReg()+1), 1188*0b57cec5SDimitry Andric Lo64)); 1189*0b57cec5SDimitry Andric continue; 1190*0b57cec5SDimitry Andric } 1191*0b57cec5SDimitry Andric 1192*0b57cec5SDimitry Andric // The custom bit on an i32 return value indicates that it should be 1193*0b57cec5SDimitry Andric // passed in the high bits of the register. 1194*0b57cec5SDimitry Andric if (VA.getValVT() == MVT::i32 && VA.needsCustom()) { 1195*0b57cec5SDimitry Andric Arg = DAG.getNode(ISD::SHL, DL, MVT::i64, Arg, 1196*0b57cec5SDimitry Andric DAG.getConstant(32, DL, MVT::i32)); 1197*0b57cec5SDimitry Andric 1198*0b57cec5SDimitry Andric // The next value may go in the low bits of the same register. 1199*0b57cec5SDimitry Andric // Handle both at once. 1200*0b57cec5SDimitry Andric if (i+1 < ArgLocs.size() && ArgLocs[i+1].isRegLoc() && 1201*0b57cec5SDimitry Andric ArgLocs[i+1].getLocReg() == VA.getLocReg()) { 1202*0b57cec5SDimitry Andric SDValue NV = DAG.getNode(ISD::ZERO_EXTEND, DL, MVT::i64, 1203*0b57cec5SDimitry Andric CLI.OutVals[i+1]); 1204*0b57cec5SDimitry Andric Arg = DAG.getNode(ISD::OR, DL, MVT::i64, Arg, NV); 1205*0b57cec5SDimitry Andric // Skip the next value, it's already done. 1206*0b57cec5SDimitry Andric ++i; 1207*0b57cec5SDimitry Andric } 1208*0b57cec5SDimitry Andric } 1209*0b57cec5SDimitry Andric RegsToPass.push_back(std::make_pair(toCallerWindow(VA.getLocReg()), Arg)); 1210*0b57cec5SDimitry Andric continue; 1211*0b57cec5SDimitry Andric } 1212*0b57cec5SDimitry Andric 1213*0b57cec5SDimitry Andric assert(VA.isMemLoc()); 1214*0b57cec5SDimitry Andric 1215*0b57cec5SDimitry Andric // Create a store off the stack pointer for this argument. 1216*0b57cec5SDimitry Andric SDValue StackPtr = DAG.getRegister(SP::O6, PtrVT); 1217*0b57cec5SDimitry Andric // The argument area starts at %fp+BIAS+128 in the callee frame, 1218*0b57cec5SDimitry Andric // %sp+BIAS+128 in ours. 1219*0b57cec5SDimitry Andric SDValue PtrOff = DAG.getIntPtrConstant(VA.getLocMemOffset() + 1220*0b57cec5SDimitry Andric Subtarget->getStackPointerBias() + 1221*0b57cec5SDimitry Andric 128, DL); 1222*0b57cec5SDimitry Andric PtrOff = DAG.getNode(ISD::ADD, DL, PtrVT, StackPtr, PtrOff); 1223*0b57cec5SDimitry Andric MemOpChains.push_back( 1224*0b57cec5SDimitry Andric DAG.getStore(Chain, DL, Arg, PtrOff, MachinePointerInfo())); 1225*0b57cec5SDimitry Andric } 1226*0b57cec5SDimitry Andric 1227*0b57cec5SDimitry Andric // Emit all stores, make sure they occur before the call. 1228*0b57cec5SDimitry Andric if (!MemOpChains.empty()) 1229*0b57cec5SDimitry Andric Chain = DAG.getNode(ISD::TokenFactor, DL, MVT::Other, MemOpChains); 1230*0b57cec5SDimitry Andric 1231*0b57cec5SDimitry Andric // Build a sequence of CopyToReg nodes glued together with token chain and 1232*0b57cec5SDimitry Andric // glue operands which copy the outgoing args into registers. The InGlue is 1233*0b57cec5SDimitry Andric // necessary since all emitted instructions must be stuck together in order 1234*0b57cec5SDimitry Andric // to pass the live physical registers. 1235*0b57cec5SDimitry Andric SDValue InGlue; 1236*0b57cec5SDimitry Andric for (unsigned i = 0, e = RegsToPass.size(); i != e; ++i) { 1237*0b57cec5SDimitry Andric Chain = DAG.getCopyToReg(Chain, DL, 1238*0b57cec5SDimitry Andric RegsToPass[i].first, RegsToPass[i].second, InGlue); 1239*0b57cec5SDimitry Andric InGlue = Chain.getValue(1); 1240*0b57cec5SDimitry Andric } 1241*0b57cec5SDimitry Andric 1242*0b57cec5SDimitry Andric // If the callee is a GlobalAddress node (quite common, every direct call is) 1243*0b57cec5SDimitry Andric // turn it into a TargetGlobalAddress node so that legalize doesn't hack it. 1244*0b57cec5SDimitry Andric // Likewise ExternalSymbol -> TargetExternalSymbol. 1245*0b57cec5SDimitry Andric SDValue Callee = CLI.Callee; 1246*0b57cec5SDimitry Andric bool hasReturnsTwice = hasReturnsTwiceAttr(DAG, Callee, CLI.CS); 1247*0b57cec5SDimitry Andric unsigned TF = isPositionIndependent() ? SparcMCExpr::VK_Sparc_WPLT30 : 0; 1248*0b57cec5SDimitry Andric if (GlobalAddressSDNode *G = dyn_cast<GlobalAddressSDNode>(Callee)) 1249*0b57cec5SDimitry Andric Callee = DAG.getTargetGlobalAddress(G->getGlobal(), DL, PtrVT, 0, TF); 1250*0b57cec5SDimitry Andric else if (ExternalSymbolSDNode *E = dyn_cast<ExternalSymbolSDNode>(Callee)) 1251*0b57cec5SDimitry Andric Callee = DAG.getTargetExternalSymbol(E->getSymbol(), PtrVT, TF); 1252*0b57cec5SDimitry Andric 1253*0b57cec5SDimitry Andric // Build the operands for the call instruction itself. 1254*0b57cec5SDimitry Andric SmallVector<SDValue, 8> Ops; 1255*0b57cec5SDimitry Andric Ops.push_back(Chain); 1256*0b57cec5SDimitry Andric Ops.push_back(Callee); 1257*0b57cec5SDimitry Andric for (unsigned i = 0, e = RegsToPass.size(); i != e; ++i) 1258*0b57cec5SDimitry Andric Ops.push_back(DAG.getRegister(RegsToPass[i].first, 1259*0b57cec5SDimitry Andric RegsToPass[i].second.getValueType())); 1260*0b57cec5SDimitry Andric 1261*0b57cec5SDimitry Andric // Add a register mask operand representing the call-preserved registers. 1262*0b57cec5SDimitry Andric const SparcRegisterInfo *TRI = Subtarget->getRegisterInfo(); 1263*0b57cec5SDimitry Andric const uint32_t *Mask = 1264*0b57cec5SDimitry Andric ((hasReturnsTwice) ? TRI->getRTCallPreservedMask(CLI.CallConv) 1265*0b57cec5SDimitry Andric : TRI->getCallPreservedMask(DAG.getMachineFunction(), 1266*0b57cec5SDimitry Andric CLI.CallConv)); 1267*0b57cec5SDimitry Andric assert(Mask && "Missing call preserved mask for calling convention"); 1268*0b57cec5SDimitry Andric Ops.push_back(DAG.getRegisterMask(Mask)); 1269*0b57cec5SDimitry Andric 1270*0b57cec5SDimitry Andric // Make sure the CopyToReg nodes are glued to the call instruction which 1271*0b57cec5SDimitry Andric // consumes the registers. 1272*0b57cec5SDimitry Andric if (InGlue.getNode()) 1273*0b57cec5SDimitry Andric Ops.push_back(InGlue); 1274*0b57cec5SDimitry Andric 1275*0b57cec5SDimitry Andric // Now the call itself. 1276*0b57cec5SDimitry Andric SDVTList NodeTys = DAG.getVTList(MVT::Other, MVT::Glue); 1277*0b57cec5SDimitry Andric Chain = DAG.getNode(SPISD::CALL, DL, NodeTys, Ops); 1278*0b57cec5SDimitry Andric InGlue = Chain.getValue(1); 1279*0b57cec5SDimitry Andric 1280*0b57cec5SDimitry Andric // Revert the stack pointer immediately after the call. 1281*0b57cec5SDimitry Andric Chain = DAG.getCALLSEQ_END(Chain, DAG.getIntPtrConstant(ArgsSize, DL, true), 1282*0b57cec5SDimitry Andric DAG.getIntPtrConstant(0, DL, true), InGlue, DL); 1283*0b57cec5SDimitry Andric InGlue = Chain.getValue(1); 1284*0b57cec5SDimitry Andric 1285*0b57cec5SDimitry Andric // Now extract the return values. This is more or less the same as 1286*0b57cec5SDimitry Andric // LowerFormalArguments_64. 1287*0b57cec5SDimitry Andric 1288*0b57cec5SDimitry Andric // Assign locations to each value returned by this call. 1289*0b57cec5SDimitry Andric SmallVector<CCValAssign, 16> RVLocs; 1290*0b57cec5SDimitry Andric CCState RVInfo(CLI.CallConv, CLI.IsVarArg, DAG.getMachineFunction(), RVLocs, 1291*0b57cec5SDimitry Andric *DAG.getContext()); 1292*0b57cec5SDimitry Andric 1293*0b57cec5SDimitry Andric // Set inreg flag manually for codegen generated library calls that 1294*0b57cec5SDimitry Andric // return float. 1295*0b57cec5SDimitry Andric if (CLI.Ins.size() == 1 && CLI.Ins[0].VT == MVT::f32 && !CLI.CS) 1296*0b57cec5SDimitry Andric CLI.Ins[0].Flags.setInReg(); 1297*0b57cec5SDimitry Andric 1298*0b57cec5SDimitry Andric RVInfo.AnalyzeCallResult(CLI.Ins, RetCC_Sparc64); 1299*0b57cec5SDimitry Andric 1300*0b57cec5SDimitry Andric // Copy all of the result registers out of their specified physreg. 1301*0b57cec5SDimitry Andric for (unsigned i = 0; i != RVLocs.size(); ++i) { 1302*0b57cec5SDimitry Andric CCValAssign &VA = RVLocs[i]; 1303*0b57cec5SDimitry Andric unsigned Reg = toCallerWindow(VA.getLocReg()); 1304*0b57cec5SDimitry Andric 1305*0b57cec5SDimitry Andric // When returning 'inreg {i32, i32 }', two consecutive i32 arguments can 1306*0b57cec5SDimitry Andric // reside in the same register in the high and low bits. Reuse the 1307*0b57cec5SDimitry Andric // CopyFromReg previous node to avoid duplicate copies. 1308*0b57cec5SDimitry Andric SDValue RV; 1309*0b57cec5SDimitry Andric if (RegisterSDNode *SrcReg = dyn_cast<RegisterSDNode>(Chain.getOperand(1))) 1310*0b57cec5SDimitry Andric if (SrcReg->getReg() == Reg && Chain->getOpcode() == ISD::CopyFromReg) 1311*0b57cec5SDimitry Andric RV = Chain.getValue(0); 1312*0b57cec5SDimitry Andric 1313*0b57cec5SDimitry Andric // But usually we'll create a new CopyFromReg for a different register. 1314*0b57cec5SDimitry Andric if (!RV.getNode()) { 1315*0b57cec5SDimitry Andric RV = DAG.getCopyFromReg(Chain, DL, Reg, RVLocs[i].getLocVT(), InGlue); 1316*0b57cec5SDimitry Andric Chain = RV.getValue(1); 1317*0b57cec5SDimitry Andric InGlue = Chain.getValue(2); 1318*0b57cec5SDimitry Andric } 1319*0b57cec5SDimitry Andric 1320*0b57cec5SDimitry Andric // Get the high bits for i32 struct elements. 1321*0b57cec5SDimitry Andric if (VA.getValVT() == MVT::i32 && VA.needsCustom()) 1322*0b57cec5SDimitry Andric RV = DAG.getNode(ISD::SRL, DL, VA.getLocVT(), RV, 1323*0b57cec5SDimitry Andric DAG.getConstant(32, DL, MVT::i32)); 1324*0b57cec5SDimitry Andric 1325*0b57cec5SDimitry Andric // The callee promoted the return value, so insert an Assert?ext SDNode so 1326*0b57cec5SDimitry Andric // we won't promote the value again in this function. 1327*0b57cec5SDimitry Andric switch (VA.getLocInfo()) { 1328*0b57cec5SDimitry Andric case CCValAssign::SExt: 1329*0b57cec5SDimitry Andric RV = DAG.getNode(ISD::AssertSext, DL, VA.getLocVT(), RV, 1330*0b57cec5SDimitry Andric DAG.getValueType(VA.getValVT())); 1331*0b57cec5SDimitry Andric break; 1332*0b57cec5SDimitry Andric case CCValAssign::ZExt: 1333*0b57cec5SDimitry Andric RV = DAG.getNode(ISD::AssertZext, DL, VA.getLocVT(), RV, 1334*0b57cec5SDimitry Andric DAG.getValueType(VA.getValVT())); 1335*0b57cec5SDimitry Andric break; 1336*0b57cec5SDimitry Andric default: 1337*0b57cec5SDimitry Andric break; 1338*0b57cec5SDimitry Andric } 1339*0b57cec5SDimitry Andric 1340*0b57cec5SDimitry Andric // Truncate the register down to the return value type. 1341*0b57cec5SDimitry Andric if (VA.isExtInLoc()) 1342*0b57cec5SDimitry Andric RV = DAG.getNode(ISD::TRUNCATE, DL, VA.getValVT(), RV); 1343*0b57cec5SDimitry Andric 1344*0b57cec5SDimitry Andric InVals.push_back(RV); 1345*0b57cec5SDimitry Andric } 1346*0b57cec5SDimitry Andric 1347*0b57cec5SDimitry Andric return Chain; 1348*0b57cec5SDimitry Andric } 1349*0b57cec5SDimitry Andric 1350*0b57cec5SDimitry Andric //===----------------------------------------------------------------------===// 1351*0b57cec5SDimitry Andric // TargetLowering Implementation 1352*0b57cec5SDimitry Andric //===----------------------------------------------------------------------===// 1353*0b57cec5SDimitry Andric 1354*0b57cec5SDimitry Andric TargetLowering::AtomicExpansionKind SparcTargetLowering::shouldExpandAtomicRMWInIR(AtomicRMWInst *AI) const { 1355*0b57cec5SDimitry Andric if (AI->getOperation() == AtomicRMWInst::Xchg && 1356*0b57cec5SDimitry Andric AI->getType()->getPrimitiveSizeInBits() == 32) 1357*0b57cec5SDimitry Andric return AtomicExpansionKind::None; // Uses xchg instruction 1358*0b57cec5SDimitry Andric 1359*0b57cec5SDimitry Andric return AtomicExpansionKind::CmpXChg; 1360*0b57cec5SDimitry Andric } 1361*0b57cec5SDimitry Andric 1362*0b57cec5SDimitry Andric /// IntCondCCodeToICC - Convert a DAG integer condition code to a SPARC ICC 1363*0b57cec5SDimitry Andric /// condition. 1364*0b57cec5SDimitry Andric static SPCC::CondCodes IntCondCCodeToICC(ISD::CondCode CC) { 1365*0b57cec5SDimitry Andric switch (CC) { 1366*0b57cec5SDimitry Andric default: llvm_unreachable("Unknown integer condition code!"); 1367*0b57cec5SDimitry Andric case ISD::SETEQ: return SPCC::ICC_E; 1368*0b57cec5SDimitry Andric case ISD::SETNE: return SPCC::ICC_NE; 1369*0b57cec5SDimitry Andric case ISD::SETLT: return SPCC::ICC_L; 1370*0b57cec5SDimitry Andric case ISD::SETGT: return SPCC::ICC_G; 1371*0b57cec5SDimitry Andric case ISD::SETLE: return SPCC::ICC_LE; 1372*0b57cec5SDimitry Andric case ISD::SETGE: return SPCC::ICC_GE; 1373*0b57cec5SDimitry Andric case ISD::SETULT: return SPCC::ICC_CS; 1374*0b57cec5SDimitry Andric case ISD::SETULE: return SPCC::ICC_LEU; 1375*0b57cec5SDimitry Andric case ISD::SETUGT: return SPCC::ICC_GU; 1376*0b57cec5SDimitry Andric case ISD::SETUGE: return SPCC::ICC_CC; 1377*0b57cec5SDimitry Andric } 1378*0b57cec5SDimitry Andric } 1379*0b57cec5SDimitry Andric 1380*0b57cec5SDimitry Andric /// FPCondCCodeToFCC - Convert a DAG floatingp oint condition code to a SPARC 1381*0b57cec5SDimitry Andric /// FCC condition. 1382*0b57cec5SDimitry Andric static SPCC::CondCodes FPCondCCodeToFCC(ISD::CondCode CC) { 1383*0b57cec5SDimitry Andric switch (CC) { 1384*0b57cec5SDimitry Andric default: llvm_unreachable("Unknown fp condition code!"); 1385*0b57cec5SDimitry Andric case ISD::SETEQ: 1386*0b57cec5SDimitry Andric case ISD::SETOEQ: return SPCC::FCC_E; 1387*0b57cec5SDimitry Andric case ISD::SETNE: 1388*0b57cec5SDimitry Andric case ISD::SETUNE: return SPCC::FCC_NE; 1389*0b57cec5SDimitry Andric case ISD::SETLT: 1390*0b57cec5SDimitry Andric case ISD::SETOLT: return SPCC::FCC_L; 1391*0b57cec5SDimitry Andric case ISD::SETGT: 1392*0b57cec5SDimitry Andric case ISD::SETOGT: return SPCC::FCC_G; 1393*0b57cec5SDimitry Andric case ISD::SETLE: 1394*0b57cec5SDimitry Andric case ISD::SETOLE: return SPCC::FCC_LE; 1395*0b57cec5SDimitry Andric case ISD::SETGE: 1396*0b57cec5SDimitry Andric case ISD::SETOGE: return SPCC::FCC_GE; 1397*0b57cec5SDimitry Andric case ISD::SETULT: return SPCC::FCC_UL; 1398*0b57cec5SDimitry Andric case ISD::SETULE: return SPCC::FCC_ULE; 1399*0b57cec5SDimitry Andric case ISD::SETUGT: return SPCC::FCC_UG; 1400*0b57cec5SDimitry Andric case ISD::SETUGE: return SPCC::FCC_UGE; 1401*0b57cec5SDimitry Andric case ISD::SETUO: return SPCC::FCC_U; 1402*0b57cec5SDimitry Andric case ISD::SETO: return SPCC::FCC_O; 1403*0b57cec5SDimitry Andric case ISD::SETONE: return SPCC::FCC_LG; 1404*0b57cec5SDimitry Andric case ISD::SETUEQ: return SPCC::FCC_UE; 1405*0b57cec5SDimitry Andric } 1406*0b57cec5SDimitry Andric } 1407*0b57cec5SDimitry Andric 1408*0b57cec5SDimitry Andric SparcTargetLowering::SparcTargetLowering(const TargetMachine &TM, 1409*0b57cec5SDimitry Andric const SparcSubtarget &STI) 1410*0b57cec5SDimitry Andric : TargetLowering(TM), Subtarget(&STI) { 1411*0b57cec5SDimitry Andric MVT PtrVT = MVT::getIntegerVT(8 * TM.getPointerSize(0)); 1412*0b57cec5SDimitry Andric 1413*0b57cec5SDimitry Andric // Instructions which use registers as conditionals examine all the 1414*0b57cec5SDimitry Andric // bits (as does the pseudo SELECT_CC expansion). I don't think it 1415*0b57cec5SDimitry Andric // matters much whether it's ZeroOrOneBooleanContent, or 1416*0b57cec5SDimitry Andric // ZeroOrNegativeOneBooleanContent, so, arbitrarily choose the 1417*0b57cec5SDimitry Andric // former. 1418*0b57cec5SDimitry Andric setBooleanContents(ZeroOrOneBooleanContent); 1419*0b57cec5SDimitry Andric setBooleanVectorContents(ZeroOrOneBooleanContent); 1420*0b57cec5SDimitry Andric 1421*0b57cec5SDimitry Andric // Set up the register classes. 1422*0b57cec5SDimitry Andric addRegisterClass(MVT::i32, &SP::IntRegsRegClass); 1423*0b57cec5SDimitry Andric if (!Subtarget->useSoftFloat()) { 1424*0b57cec5SDimitry Andric addRegisterClass(MVT::f32, &SP::FPRegsRegClass); 1425*0b57cec5SDimitry Andric addRegisterClass(MVT::f64, &SP::DFPRegsRegClass); 1426*0b57cec5SDimitry Andric addRegisterClass(MVT::f128, &SP::QFPRegsRegClass); 1427*0b57cec5SDimitry Andric } 1428*0b57cec5SDimitry Andric if (Subtarget->is64Bit()) { 1429*0b57cec5SDimitry Andric addRegisterClass(MVT::i64, &SP::I64RegsRegClass); 1430*0b57cec5SDimitry Andric } else { 1431*0b57cec5SDimitry Andric // On 32bit sparc, we define a double-register 32bit register 1432*0b57cec5SDimitry Andric // class, as well. This is modeled in LLVM as a 2-vector of i32. 1433*0b57cec5SDimitry Andric addRegisterClass(MVT::v2i32, &SP::IntPairRegClass); 1434*0b57cec5SDimitry Andric 1435*0b57cec5SDimitry Andric // ...but almost all operations must be expanded, so set that as 1436*0b57cec5SDimitry Andric // the default. 1437*0b57cec5SDimitry Andric for (unsigned Op = 0; Op < ISD::BUILTIN_OP_END; ++Op) { 1438*0b57cec5SDimitry Andric setOperationAction(Op, MVT::v2i32, Expand); 1439*0b57cec5SDimitry Andric } 1440*0b57cec5SDimitry Andric // Truncating/extending stores/loads are also not supported. 1441*0b57cec5SDimitry Andric for (MVT VT : MVT::integer_vector_valuetypes()) { 1442*0b57cec5SDimitry Andric setLoadExtAction(ISD::SEXTLOAD, VT, MVT::v2i32, Expand); 1443*0b57cec5SDimitry Andric setLoadExtAction(ISD::ZEXTLOAD, VT, MVT::v2i32, Expand); 1444*0b57cec5SDimitry Andric setLoadExtAction(ISD::EXTLOAD, VT, MVT::v2i32, Expand); 1445*0b57cec5SDimitry Andric 1446*0b57cec5SDimitry Andric setLoadExtAction(ISD::SEXTLOAD, MVT::v2i32, VT, Expand); 1447*0b57cec5SDimitry Andric setLoadExtAction(ISD::ZEXTLOAD, MVT::v2i32, VT, Expand); 1448*0b57cec5SDimitry Andric setLoadExtAction(ISD::EXTLOAD, MVT::v2i32, VT, Expand); 1449*0b57cec5SDimitry Andric 1450*0b57cec5SDimitry Andric setTruncStoreAction(VT, MVT::v2i32, Expand); 1451*0b57cec5SDimitry Andric setTruncStoreAction(MVT::v2i32, VT, Expand); 1452*0b57cec5SDimitry Andric } 1453*0b57cec5SDimitry Andric // However, load and store *are* legal. 1454*0b57cec5SDimitry Andric setOperationAction(ISD::LOAD, MVT::v2i32, Legal); 1455*0b57cec5SDimitry Andric setOperationAction(ISD::STORE, MVT::v2i32, Legal); 1456*0b57cec5SDimitry Andric setOperationAction(ISD::EXTRACT_VECTOR_ELT, MVT::v2i32, Legal); 1457*0b57cec5SDimitry Andric setOperationAction(ISD::BUILD_VECTOR, MVT::v2i32, Legal); 1458*0b57cec5SDimitry Andric 1459*0b57cec5SDimitry Andric // And we need to promote i64 loads/stores into vector load/store 1460*0b57cec5SDimitry Andric setOperationAction(ISD::LOAD, MVT::i64, Custom); 1461*0b57cec5SDimitry Andric setOperationAction(ISD::STORE, MVT::i64, Custom); 1462*0b57cec5SDimitry Andric 1463*0b57cec5SDimitry Andric // Sadly, this doesn't work: 1464*0b57cec5SDimitry Andric // AddPromotedToType(ISD::LOAD, MVT::i64, MVT::v2i32); 1465*0b57cec5SDimitry Andric // AddPromotedToType(ISD::STORE, MVT::i64, MVT::v2i32); 1466*0b57cec5SDimitry Andric } 1467*0b57cec5SDimitry Andric 1468*0b57cec5SDimitry Andric // Turn FP extload into load/fpextend 1469*0b57cec5SDimitry Andric for (MVT VT : MVT::fp_valuetypes()) { 1470*0b57cec5SDimitry Andric setLoadExtAction(ISD::EXTLOAD, VT, MVT::f32, Expand); 1471*0b57cec5SDimitry Andric setLoadExtAction(ISD::EXTLOAD, VT, MVT::f64, Expand); 1472*0b57cec5SDimitry Andric } 1473*0b57cec5SDimitry Andric 1474*0b57cec5SDimitry Andric // Sparc doesn't have i1 sign extending load 1475*0b57cec5SDimitry Andric for (MVT VT : MVT::integer_valuetypes()) 1476*0b57cec5SDimitry Andric setLoadExtAction(ISD::SEXTLOAD, VT, MVT::i1, Promote); 1477*0b57cec5SDimitry Andric 1478*0b57cec5SDimitry Andric // Turn FP truncstore into trunc + store. 1479*0b57cec5SDimitry Andric setTruncStoreAction(MVT::f64, MVT::f32, Expand); 1480*0b57cec5SDimitry Andric setTruncStoreAction(MVT::f128, MVT::f32, Expand); 1481*0b57cec5SDimitry Andric setTruncStoreAction(MVT::f128, MVT::f64, Expand); 1482*0b57cec5SDimitry Andric 1483*0b57cec5SDimitry Andric // Custom legalize GlobalAddress nodes into LO/HI parts. 1484*0b57cec5SDimitry Andric setOperationAction(ISD::GlobalAddress, PtrVT, Custom); 1485*0b57cec5SDimitry Andric setOperationAction(ISD::GlobalTLSAddress, PtrVT, Custom); 1486*0b57cec5SDimitry Andric setOperationAction(ISD::ConstantPool, PtrVT, Custom); 1487*0b57cec5SDimitry Andric setOperationAction(ISD::BlockAddress, PtrVT, Custom); 1488*0b57cec5SDimitry Andric 1489*0b57cec5SDimitry Andric // Sparc doesn't have sext_inreg, replace them with shl/sra 1490*0b57cec5SDimitry Andric setOperationAction(ISD::SIGN_EXTEND_INREG, MVT::i16, Expand); 1491*0b57cec5SDimitry Andric setOperationAction(ISD::SIGN_EXTEND_INREG, MVT::i8 , Expand); 1492*0b57cec5SDimitry Andric setOperationAction(ISD::SIGN_EXTEND_INREG, MVT::i1 , Expand); 1493*0b57cec5SDimitry Andric 1494*0b57cec5SDimitry Andric // Sparc has no REM or DIVREM operations. 1495*0b57cec5SDimitry Andric setOperationAction(ISD::UREM, MVT::i32, Expand); 1496*0b57cec5SDimitry Andric setOperationAction(ISD::SREM, MVT::i32, Expand); 1497*0b57cec5SDimitry Andric setOperationAction(ISD::SDIVREM, MVT::i32, Expand); 1498*0b57cec5SDimitry Andric setOperationAction(ISD::UDIVREM, MVT::i32, Expand); 1499*0b57cec5SDimitry Andric 1500*0b57cec5SDimitry Andric // ... nor does SparcV9. 1501*0b57cec5SDimitry Andric if (Subtarget->is64Bit()) { 1502*0b57cec5SDimitry Andric setOperationAction(ISD::UREM, MVT::i64, Expand); 1503*0b57cec5SDimitry Andric setOperationAction(ISD::SREM, MVT::i64, Expand); 1504*0b57cec5SDimitry Andric setOperationAction(ISD::SDIVREM, MVT::i64, Expand); 1505*0b57cec5SDimitry Andric setOperationAction(ISD::UDIVREM, MVT::i64, Expand); 1506*0b57cec5SDimitry Andric } 1507*0b57cec5SDimitry Andric 1508*0b57cec5SDimitry Andric // Custom expand fp<->sint 1509*0b57cec5SDimitry Andric setOperationAction(ISD::FP_TO_SINT, MVT::i32, Custom); 1510*0b57cec5SDimitry Andric setOperationAction(ISD::SINT_TO_FP, MVT::i32, Custom); 1511*0b57cec5SDimitry Andric setOperationAction(ISD::FP_TO_SINT, MVT::i64, Custom); 1512*0b57cec5SDimitry Andric setOperationAction(ISD::SINT_TO_FP, MVT::i64, Custom); 1513*0b57cec5SDimitry Andric 1514*0b57cec5SDimitry Andric // Custom Expand fp<->uint 1515*0b57cec5SDimitry Andric setOperationAction(ISD::FP_TO_UINT, MVT::i32, Custom); 1516*0b57cec5SDimitry Andric setOperationAction(ISD::UINT_TO_FP, MVT::i32, Custom); 1517*0b57cec5SDimitry Andric setOperationAction(ISD::FP_TO_UINT, MVT::i64, Custom); 1518*0b57cec5SDimitry Andric setOperationAction(ISD::UINT_TO_FP, MVT::i64, Custom); 1519*0b57cec5SDimitry Andric 1520*0b57cec5SDimitry Andric setOperationAction(ISD::BITCAST, MVT::f32, Expand); 1521*0b57cec5SDimitry Andric setOperationAction(ISD::BITCAST, MVT::i32, Expand); 1522*0b57cec5SDimitry Andric 1523*0b57cec5SDimitry Andric // Sparc has no select or setcc: expand to SELECT_CC. 1524*0b57cec5SDimitry Andric setOperationAction(ISD::SELECT, MVT::i32, Expand); 1525*0b57cec5SDimitry Andric setOperationAction(ISD::SELECT, MVT::f32, Expand); 1526*0b57cec5SDimitry Andric setOperationAction(ISD::SELECT, MVT::f64, Expand); 1527*0b57cec5SDimitry Andric setOperationAction(ISD::SELECT, MVT::f128, Expand); 1528*0b57cec5SDimitry Andric 1529*0b57cec5SDimitry Andric setOperationAction(ISD::SETCC, MVT::i32, Expand); 1530*0b57cec5SDimitry Andric setOperationAction(ISD::SETCC, MVT::f32, Expand); 1531*0b57cec5SDimitry Andric setOperationAction(ISD::SETCC, MVT::f64, Expand); 1532*0b57cec5SDimitry Andric setOperationAction(ISD::SETCC, MVT::f128, Expand); 1533*0b57cec5SDimitry Andric 1534*0b57cec5SDimitry Andric // Sparc doesn't have BRCOND either, it has BR_CC. 1535*0b57cec5SDimitry Andric setOperationAction(ISD::BRCOND, MVT::Other, Expand); 1536*0b57cec5SDimitry Andric setOperationAction(ISD::BRIND, MVT::Other, Expand); 1537*0b57cec5SDimitry Andric setOperationAction(ISD::BR_JT, MVT::Other, Expand); 1538*0b57cec5SDimitry Andric setOperationAction(ISD::BR_CC, MVT::i32, Custom); 1539*0b57cec5SDimitry Andric setOperationAction(ISD::BR_CC, MVT::f32, Custom); 1540*0b57cec5SDimitry Andric setOperationAction(ISD::BR_CC, MVT::f64, Custom); 1541*0b57cec5SDimitry Andric setOperationAction(ISD::BR_CC, MVT::f128, Custom); 1542*0b57cec5SDimitry Andric 1543*0b57cec5SDimitry Andric setOperationAction(ISD::SELECT_CC, MVT::i32, Custom); 1544*0b57cec5SDimitry Andric setOperationAction(ISD::SELECT_CC, MVT::f32, Custom); 1545*0b57cec5SDimitry Andric setOperationAction(ISD::SELECT_CC, MVT::f64, Custom); 1546*0b57cec5SDimitry Andric setOperationAction(ISD::SELECT_CC, MVT::f128, Custom); 1547*0b57cec5SDimitry Andric 1548*0b57cec5SDimitry Andric setOperationAction(ISD::ADDC, MVT::i32, Custom); 1549*0b57cec5SDimitry Andric setOperationAction(ISD::ADDE, MVT::i32, Custom); 1550*0b57cec5SDimitry Andric setOperationAction(ISD::SUBC, MVT::i32, Custom); 1551*0b57cec5SDimitry Andric setOperationAction(ISD::SUBE, MVT::i32, Custom); 1552*0b57cec5SDimitry Andric 1553*0b57cec5SDimitry Andric if (Subtarget->is64Bit()) { 1554*0b57cec5SDimitry Andric setOperationAction(ISD::ADDC, MVT::i64, Custom); 1555*0b57cec5SDimitry Andric setOperationAction(ISD::ADDE, MVT::i64, Custom); 1556*0b57cec5SDimitry Andric setOperationAction(ISD::SUBC, MVT::i64, Custom); 1557*0b57cec5SDimitry Andric setOperationAction(ISD::SUBE, MVT::i64, Custom); 1558*0b57cec5SDimitry Andric setOperationAction(ISD::BITCAST, MVT::f64, Expand); 1559*0b57cec5SDimitry Andric setOperationAction(ISD::BITCAST, MVT::i64, Expand); 1560*0b57cec5SDimitry Andric setOperationAction(ISD::SELECT, MVT::i64, Expand); 1561*0b57cec5SDimitry Andric setOperationAction(ISD::SETCC, MVT::i64, Expand); 1562*0b57cec5SDimitry Andric setOperationAction(ISD::BR_CC, MVT::i64, Custom); 1563*0b57cec5SDimitry Andric setOperationAction(ISD::SELECT_CC, MVT::i64, Custom); 1564*0b57cec5SDimitry Andric 1565*0b57cec5SDimitry Andric setOperationAction(ISD::CTPOP, MVT::i64, 1566*0b57cec5SDimitry Andric Subtarget->usePopc() ? Legal : Expand); 1567*0b57cec5SDimitry Andric setOperationAction(ISD::CTTZ , MVT::i64, Expand); 1568*0b57cec5SDimitry Andric setOperationAction(ISD::CTLZ , MVT::i64, Expand); 1569*0b57cec5SDimitry Andric setOperationAction(ISD::BSWAP, MVT::i64, Expand); 1570*0b57cec5SDimitry Andric setOperationAction(ISD::ROTL , MVT::i64, Expand); 1571*0b57cec5SDimitry Andric setOperationAction(ISD::ROTR , MVT::i64, Expand); 1572*0b57cec5SDimitry Andric setOperationAction(ISD::DYNAMIC_STACKALLOC, MVT::i64, Custom); 1573*0b57cec5SDimitry Andric } 1574*0b57cec5SDimitry Andric 1575*0b57cec5SDimitry Andric // ATOMICs. 1576*0b57cec5SDimitry Andric // Atomics are supported on SparcV9. 32-bit atomics are also 1577*0b57cec5SDimitry Andric // supported by some Leon SparcV8 variants. Otherwise, atomics 1578*0b57cec5SDimitry Andric // are unsupported. 1579*0b57cec5SDimitry Andric if (Subtarget->isV9()) 1580*0b57cec5SDimitry Andric setMaxAtomicSizeInBitsSupported(64); 1581*0b57cec5SDimitry Andric else if (Subtarget->hasLeonCasa()) 1582*0b57cec5SDimitry Andric setMaxAtomicSizeInBitsSupported(32); 1583*0b57cec5SDimitry Andric else 1584*0b57cec5SDimitry Andric setMaxAtomicSizeInBitsSupported(0); 1585*0b57cec5SDimitry Andric 1586*0b57cec5SDimitry Andric setMinCmpXchgSizeInBits(32); 1587*0b57cec5SDimitry Andric 1588*0b57cec5SDimitry Andric setOperationAction(ISD::ATOMIC_SWAP, MVT::i32, Legal); 1589*0b57cec5SDimitry Andric 1590*0b57cec5SDimitry Andric setOperationAction(ISD::ATOMIC_FENCE, MVT::Other, Legal); 1591*0b57cec5SDimitry Andric 1592*0b57cec5SDimitry Andric // Custom Lower Atomic LOAD/STORE 1593*0b57cec5SDimitry Andric setOperationAction(ISD::ATOMIC_LOAD, MVT::i32, Custom); 1594*0b57cec5SDimitry Andric setOperationAction(ISD::ATOMIC_STORE, MVT::i32, Custom); 1595*0b57cec5SDimitry Andric 1596*0b57cec5SDimitry Andric if (Subtarget->is64Bit()) { 1597*0b57cec5SDimitry Andric setOperationAction(ISD::ATOMIC_CMP_SWAP, MVT::i64, Legal); 1598*0b57cec5SDimitry Andric setOperationAction(ISD::ATOMIC_SWAP, MVT::i64, Legal); 1599*0b57cec5SDimitry Andric setOperationAction(ISD::ATOMIC_LOAD, MVT::i64, Custom); 1600*0b57cec5SDimitry Andric setOperationAction(ISD::ATOMIC_STORE, MVT::i64, Custom); 1601*0b57cec5SDimitry Andric } 1602*0b57cec5SDimitry Andric 1603*0b57cec5SDimitry Andric if (!Subtarget->is64Bit()) { 1604*0b57cec5SDimitry Andric // These libcalls are not available in 32-bit. 1605*0b57cec5SDimitry Andric setLibcallName(RTLIB::SHL_I128, nullptr); 1606*0b57cec5SDimitry Andric setLibcallName(RTLIB::SRL_I128, nullptr); 1607*0b57cec5SDimitry Andric setLibcallName(RTLIB::SRA_I128, nullptr); 1608*0b57cec5SDimitry Andric } 1609*0b57cec5SDimitry Andric 1610*0b57cec5SDimitry Andric if (!Subtarget->isV9()) { 1611*0b57cec5SDimitry Andric // SparcV8 does not have FNEGD and FABSD. 1612*0b57cec5SDimitry Andric setOperationAction(ISD::FNEG, MVT::f64, Custom); 1613*0b57cec5SDimitry Andric setOperationAction(ISD::FABS, MVT::f64, Custom); 1614*0b57cec5SDimitry Andric } 1615*0b57cec5SDimitry Andric 1616*0b57cec5SDimitry Andric setOperationAction(ISD::FSIN , MVT::f128, Expand); 1617*0b57cec5SDimitry Andric setOperationAction(ISD::FCOS , MVT::f128, Expand); 1618*0b57cec5SDimitry Andric setOperationAction(ISD::FSINCOS, MVT::f128, Expand); 1619*0b57cec5SDimitry Andric setOperationAction(ISD::FREM , MVT::f128, Expand); 1620*0b57cec5SDimitry Andric setOperationAction(ISD::FMA , MVT::f128, Expand); 1621*0b57cec5SDimitry Andric setOperationAction(ISD::FSIN , MVT::f64, Expand); 1622*0b57cec5SDimitry Andric setOperationAction(ISD::FCOS , MVT::f64, Expand); 1623*0b57cec5SDimitry Andric setOperationAction(ISD::FSINCOS, MVT::f64, Expand); 1624*0b57cec5SDimitry Andric setOperationAction(ISD::FREM , MVT::f64, Expand); 1625*0b57cec5SDimitry Andric setOperationAction(ISD::FMA , MVT::f64, Expand); 1626*0b57cec5SDimitry Andric setOperationAction(ISD::FSIN , MVT::f32, Expand); 1627*0b57cec5SDimitry Andric setOperationAction(ISD::FCOS , MVT::f32, Expand); 1628*0b57cec5SDimitry Andric setOperationAction(ISD::FSINCOS, MVT::f32, Expand); 1629*0b57cec5SDimitry Andric setOperationAction(ISD::FREM , MVT::f32, Expand); 1630*0b57cec5SDimitry Andric setOperationAction(ISD::FMA , MVT::f32, Expand); 1631*0b57cec5SDimitry Andric setOperationAction(ISD::CTTZ , MVT::i32, Expand); 1632*0b57cec5SDimitry Andric setOperationAction(ISD::CTLZ , MVT::i32, Expand); 1633*0b57cec5SDimitry Andric setOperationAction(ISD::ROTL , MVT::i32, Expand); 1634*0b57cec5SDimitry Andric setOperationAction(ISD::ROTR , MVT::i32, Expand); 1635*0b57cec5SDimitry Andric setOperationAction(ISD::BSWAP, MVT::i32, Expand); 1636*0b57cec5SDimitry Andric setOperationAction(ISD::FCOPYSIGN, MVT::f128, Expand); 1637*0b57cec5SDimitry Andric setOperationAction(ISD::FCOPYSIGN, MVT::f64, Expand); 1638*0b57cec5SDimitry Andric setOperationAction(ISD::FCOPYSIGN, MVT::f32, Expand); 1639*0b57cec5SDimitry Andric setOperationAction(ISD::FPOW , MVT::f128, Expand); 1640*0b57cec5SDimitry Andric setOperationAction(ISD::FPOW , MVT::f64, Expand); 1641*0b57cec5SDimitry Andric setOperationAction(ISD::FPOW , MVT::f32, Expand); 1642*0b57cec5SDimitry Andric 1643*0b57cec5SDimitry Andric setOperationAction(ISD::SHL_PARTS, MVT::i32, Expand); 1644*0b57cec5SDimitry Andric setOperationAction(ISD::SRA_PARTS, MVT::i32, Expand); 1645*0b57cec5SDimitry Andric setOperationAction(ISD::SRL_PARTS, MVT::i32, Expand); 1646*0b57cec5SDimitry Andric 1647*0b57cec5SDimitry Andric // Expands to [SU]MUL_LOHI. 1648*0b57cec5SDimitry Andric setOperationAction(ISD::MULHU, MVT::i32, Expand); 1649*0b57cec5SDimitry Andric setOperationAction(ISD::MULHS, MVT::i32, Expand); 1650*0b57cec5SDimitry Andric setOperationAction(ISD::MUL, MVT::i32, Expand); 1651*0b57cec5SDimitry Andric 1652*0b57cec5SDimitry Andric if (Subtarget->useSoftMulDiv()) { 1653*0b57cec5SDimitry Andric // .umul works for both signed and unsigned 1654*0b57cec5SDimitry Andric setOperationAction(ISD::SMUL_LOHI, MVT::i32, Expand); 1655*0b57cec5SDimitry Andric setOperationAction(ISD::UMUL_LOHI, MVT::i32, Expand); 1656*0b57cec5SDimitry Andric setLibcallName(RTLIB::MUL_I32, ".umul"); 1657*0b57cec5SDimitry Andric 1658*0b57cec5SDimitry Andric setOperationAction(ISD::SDIV, MVT::i32, Expand); 1659*0b57cec5SDimitry Andric setLibcallName(RTLIB::SDIV_I32, ".div"); 1660*0b57cec5SDimitry Andric 1661*0b57cec5SDimitry Andric setOperationAction(ISD::UDIV, MVT::i32, Expand); 1662*0b57cec5SDimitry Andric setLibcallName(RTLIB::UDIV_I32, ".udiv"); 1663*0b57cec5SDimitry Andric 1664*0b57cec5SDimitry Andric setLibcallName(RTLIB::SREM_I32, ".rem"); 1665*0b57cec5SDimitry Andric setLibcallName(RTLIB::UREM_I32, ".urem"); 1666*0b57cec5SDimitry Andric } 1667*0b57cec5SDimitry Andric 1668*0b57cec5SDimitry Andric if (Subtarget->is64Bit()) { 1669*0b57cec5SDimitry Andric setOperationAction(ISD::UMUL_LOHI, MVT::i64, Expand); 1670*0b57cec5SDimitry Andric setOperationAction(ISD::SMUL_LOHI, MVT::i64, Expand); 1671*0b57cec5SDimitry Andric setOperationAction(ISD::MULHU, MVT::i64, Expand); 1672*0b57cec5SDimitry Andric setOperationAction(ISD::MULHS, MVT::i64, Expand); 1673*0b57cec5SDimitry Andric 1674*0b57cec5SDimitry Andric setOperationAction(ISD::UMULO, MVT::i64, Custom); 1675*0b57cec5SDimitry Andric setOperationAction(ISD::SMULO, MVT::i64, Custom); 1676*0b57cec5SDimitry Andric 1677*0b57cec5SDimitry Andric setOperationAction(ISD::SHL_PARTS, MVT::i64, Expand); 1678*0b57cec5SDimitry Andric setOperationAction(ISD::SRA_PARTS, MVT::i64, Expand); 1679*0b57cec5SDimitry Andric setOperationAction(ISD::SRL_PARTS, MVT::i64, Expand); 1680*0b57cec5SDimitry Andric } 1681*0b57cec5SDimitry Andric 1682*0b57cec5SDimitry Andric // VASTART needs to be custom lowered to use the VarArgsFrameIndex. 1683*0b57cec5SDimitry Andric setOperationAction(ISD::VASTART , MVT::Other, Custom); 1684*0b57cec5SDimitry Andric // VAARG needs to be lowered to not do unaligned accesses for doubles. 1685*0b57cec5SDimitry Andric setOperationAction(ISD::VAARG , MVT::Other, Custom); 1686*0b57cec5SDimitry Andric 1687*0b57cec5SDimitry Andric setOperationAction(ISD::TRAP , MVT::Other, Legal); 1688*0b57cec5SDimitry Andric setOperationAction(ISD::DEBUGTRAP , MVT::Other, Legal); 1689*0b57cec5SDimitry Andric 1690*0b57cec5SDimitry Andric // Use the default implementation. 1691*0b57cec5SDimitry Andric setOperationAction(ISD::VACOPY , MVT::Other, Expand); 1692*0b57cec5SDimitry Andric setOperationAction(ISD::VAEND , MVT::Other, Expand); 1693*0b57cec5SDimitry Andric setOperationAction(ISD::STACKSAVE , MVT::Other, Expand); 1694*0b57cec5SDimitry Andric setOperationAction(ISD::STACKRESTORE , MVT::Other, Expand); 1695*0b57cec5SDimitry Andric setOperationAction(ISD::DYNAMIC_STACKALLOC, MVT::i32 , Custom); 1696*0b57cec5SDimitry Andric 1697*0b57cec5SDimitry Andric setStackPointerRegisterToSaveRestore(SP::O6); 1698*0b57cec5SDimitry Andric 1699*0b57cec5SDimitry Andric setOperationAction(ISD::CTPOP, MVT::i32, 1700*0b57cec5SDimitry Andric Subtarget->usePopc() ? Legal : Expand); 1701*0b57cec5SDimitry Andric 1702*0b57cec5SDimitry Andric if (Subtarget->isV9() && Subtarget->hasHardQuad()) { 1703*0b57cec5SDimitry Andric setOperationAction(ISD::LOAD, MVT::f128, Legal); 1704*0b57cec5SDimitry Andric setOperationAction(ISD::STORE, MVT::f128, Legal); 1705*0b57cec5SDimitry Andric } else { 1706*0b57cec5SDimitry Andric setOperationAction(ISD::LOAD, MVT::f128, Custom); 1707*0b57cec5SDimitry Andric setOperationAction(ISD::STORE, MVT::f128, Custom); 1708*0b57cec5SDimitry Andric } 1709*0b57cec5SDimitry Andric 1710*0b57cec5SDimitry Andric if (Subtarget->hasHardQuad()) { 1711*0b57cec5SDimitry Andric setOperationAction(ISD::FADD, MVT::f128, Legal); 1712*0b57cec5SDimitry Andric setOperationAction(ISD::FSUB, MVT::f128, Legal); 1713*0b57cec5SDimitry Andric setOperationAction(ISD::FMUL, MVT::f128, Legal); 1714*0b57cec5SDimitry Andric setOperationAction(ISD::FDIV, MVT::f128, Legal); 1715*0b57cec5SDimitry Andric setOperationAction(ISD::FSQRT, MVT::f128, Legal); 1716*0b57cec5SDimitry Andric setOperationAction(ISD::FP_EXTEND, MVT::f128, Legal); 1717*0b57cec5SDimitry Andric setOperationAction(ISD::FP_ROUND, MVT::f64, Legal); 1718*0b57cec5SDimitry Andric if (Subtarget->isV9()) { 1719*0b57cec5SDimitry Andric setOperationAction(ISD::FNEG, MVT::f128, Legal); 1720*0b57cec5SDimitry Andric setOperationAction(ISD::FABS, MVT::f128, Legal); 1721*0b57cec5SDimitry Andric } else { 1722*0b57cec5SDimitry Andric setOperationAction(ISD::FNEG, MVT::f128, Custom); 1723*0b57cec5SDimitry Andric setOperationAction(ISD::FABS, MVT::f128, Custom); 1724*0b57cec5SDimitry Andric } 1725*0b57cec5SDimitry Andric 1726*0b57cec5SDimitry Andric if (!Subtarget->is64Bit()) { 1727*0b57cec5SDimitry Andric setLibcallName(RTLIB::FPTOSINT_F128_I64, "_Q_qtoll"); 1728*0b57cec5SDimitry Andric setLibcallName(RTLIB::FPTOUINT_F128_I64, "_Q_qtoull"); 1729*0b57cec5SDimitry Andric setLibcallName(RTLIB::SINTTOFP_I64_F128, "_Q_lltoq"); 1730*0b57cec5SDimitry Andric setLibcallName(RTLIB::UINTTOFP_I64_F128, "_Q_ulltoq"); 1731*0b57cec5SDimitry Andric } 1732*0b57cec5SDimitry Andric 1733*0b57cec5SDimitry Andric } else { 1734*0b57cec5SDimitry Andric // Custom legalize f128 operations. 1735*0b57cec5SDimitry Andric 1736*0b57cec5SDimitry Andric setOperationAction(ISD::FADD, MVT::f128, Custom); 1737*0b57cec5SDimitry Andric setOperationAction(ISD::FSUB, MVT::f128, Custom); 1738*0b57cec5SDimitry Andric setOperationAction(ISD::FMUL, MVT::f128, Custom); 1739*0b57cec5SDimitry Andric setOperationAction(ISD::FDIV, MVT::f128, Custom); 1740*0b57cec5SDimitry Andric setOperationAction(ISD::FSQRT, MVT::f128, Custom); 1741*0b57cec5SDimitry Andric setOperationAction(ISD::FNEG, MVT::f128, Custom); 1742*0b57cec5SDimitry Andric setOperationAction(ISD::FABS, MVT::f128, Custom); 1743*0b57cec5SDimitry Andric 1744*0b57cec5SDimitry Andric setOperationAction(ISD::FP_EXTEND, MVT::f128, Custom); 1745*0b57cec5SDimitry Andric setOperationAction(ISD::FP_ROUND, MVT::f64, Custom); 1746*0b57cec5SDimitry Andric setOperationAction(ISD::FP_ROUND, MVT::f32, Custom); 1747*0b57cec5SDimitry Andric 1748*0b57cec5SDimitry Andric // Setup Runtime library names. 1749*0b57cec5SDimitry Andric if (Subtarget->is64Bit() && !Subtarget->useSoftFloat()) { 1750*0b57cec5SDimitry Andric setLibcallName(RTLIB::ADD_F128, "_Qp_add"); 1751*0b57cec5SDimitry Andric setLibcallName(RTLIB::SUB_F128, "_Qp_sub"); 1752*0b57cec5SDimitry Andric setLibcallName(RTLIB::MUL_F128, "_Qp_mul"); 1753*0b57cec5SDimitry Andric setLibcallName(RTLIB::DIV_F128, "_Qp_div"); 1754*0b57cec5SDimitry Andric setLibcallName(RTLIB::SQRT_F128, "_Qp_sqrt"); 1755*0b57cec5SDimitry Andric setLibcallName(RTLIB::FPTOSINT_F128_I32, "_Qp_qtoi"); 1756*0b57cec5SDimitry Andric setLibcallName(RTLIB::FPTOUINT_F128_I32, "_Qp_qtoui"); 1757*0b57cec5SDimitry Andric setLibcallName(RTLIB::SINTTOFP_I32_F128, "_Qp_itoq"); 1758*0b57cec5SDimitry Andric setLibcallName(RTLIB::UINTTOFP_I32_F128, "_Qp_uitoq"); 1759*0b57cec5SDimitry Andric setLibcallName(RTLIB::FPTOSINT_F128_I64, "_Qp_qtox"); 1760*0b57cec5SDimitry Andric setLibcallName(RTLIB::FPTOUINT_F128_I64, "_Qp_qtoux"); 1761*0b57cec5SDimitry Andric setLibcallName(RTLIB::SINTTOFP_I64_F128, "_Qp_xtoq"); 1762*0b57cec5SDimitry Andric setLibcallName(RTLIB::UINTTOFP_I64_F128, "_Qp_uxtoq"); 1763*0b57cec5SDimitry Andric setLibcallName(RTLIB::FPEXT_F32_F128, "_Qp_stoq"); 1764*0b57cec5SDimitry Andric setLibcallName(RTLIB::FPEXT_F64_F128, "_Qp_dtoq"); 1765*0b57cec5SDimitry Andric setLibcallName(RTLIB::FPROUND_F128_F32, "_Qp_qtos"); 1766*0b57cec5SDimitry Andric setLibcallName(RTLIB::FPROUND_F128_F64, "_Qp_qtod"); 1767*0b57cec5SDimitry Andric } else if (!Subtarget->useSoftFloat()) { 1768*0b57cec5SDimitry Andric setLibcallName(RTLIB::ADD_F128, "_Q_add"); 1769*0b57cec5SDimitry Andric setLibcallName(RTLIB::SUB_F128, "_Q_sub"); 1770*0b57cec5SDimitry Andric setLibcallName(RTLIB::MUL_F128, "_Q_mul"); 1771*0b57cec5SDimitry Andric setLibcallName(RTLIB::DIV_F128, "_Q_div"); 1772*0b57cec5SDimitry Andric setLibcallName(RTLIB::SQRT_F128, "_Q_sqrt"); 1773*0b57cec5SDimitry Andric setLibcallName(RTLIB::FPTOSINT_F128_I32, "_Q_qtoi"); 1774*0b57cec5SDimitry Andric setLibcallName(RTLIB::FPTOUINT_F128_I32, "_Q_qtou"); 1775*0b57cec5SDimitry Andric setLibcallName(RTLIB::SINTTOFP_I32_F128, "_Q_itoq"); 1776*0b57cec5SDimitry Andric setLibcallName(RTLIB::UINTTOFP_I32_F128, "_Q_utoq"); 1777*0b57cec5SDimitry Andric setLibcallName(RTLIB::FPTOSINT_F128_I64, "_Q_qtoll"); 1778*0b57cec5SDimitry Andric setLibcallName(RTLIB::FPTOUINT_F128_I64, "_Q_qtoull"); 1779*0b57cec5SDimitry Andric setLibcallName(RTLIB::SINTTOFP_I64_F128, "_Q_lltoq"); 1780*0b57cec5SDimitry Andric setLibcallName(RTLIB::UINTTOFP_I64_F128, "_Q_ulltoq"); 1781*0b57cec5SDimitry Andric setLibcallName(RTLIB::FPEXT_F32_F128, "_Q_stoq"); 1782*0b57cec5SDimitry Andric setLibcallName(RTLIB::FPEXT_F64_F128, "_Q_dtoq"); 1783*0b57cec5SDimitry Andric setLibcallName(RTLIB::FPROUND_F128_F32, "_Q_qtos"); 1784*0b57cec5SDimitry Andric setLibcallName(RTLIB::FPROUND_F128_F64, "_Q_qtod"); 1785*0b57cec5SDimitry Andric } 1786*0b57cec5SDimitry Andric } 1787*0b57cec5SDimitry Andric 1788*0b57cec5SDimitry Andric if (Subtarget->fixAllFDIVSQRT()) { 1789*0b57cec5SDimitry Andric // Promote FDIVS and FSQRTS to FDIVD and FSQRTD instructions instead as 1790*0b57cec5SDimitry Andric // the former instructions generate errata on LEON processors. 1791*0b57cec5SDimitry Andric setOperationAction(ISD::FDIV, MVT::f32, Promote); 1792*0b57cec5SDimitry Andric setOperationAction(ISD::FSQRT, MVT::f32, Promote); 1793*0b57cec5SDimitry Andric } 1794*0b57cec5SDimitry Andric 1795*0b57cec5SDimitry Andric if (Subtarget->hasNoFMULS()) { 1796*0b57cec5SDimitry Andric setOperationAction(ISD::FMUL, MVT::f32, Promote); 1797*0b57cec5SDimitry Andric } 1798*0b57cec5SDimitry Andric 1799*0b57cec5SDimitry Andric // Custom combine bitcast between f64 and v2i32 1800*0b57cec5SDimitry Andric if (!Subtarget->is64Bit()) 1801*0b57cec5SDimitry Andric setTargetDAGCombine(ISD::BITCAST); 1802*0b57cec5SDimitry Andric 1803*0b57cec5SDimitry Andric if (Subtarget->hasLeonCycleCounter()) 1804*0b57cec5SDimitry Andric setOperationAction(ISD::READCYCLECOUNTER, MVT::i64, Custom); 1805*0b57cec5SDimitry Andric 1806*0b57cec5SDimitry Andric setOperationAction(ISD::INTRINSIC_WO_CHAIN, MVT::Other, Custom); 1807*0b57cec5SDimitry Andric 1808*0b57cec5SDimitry Andric setMinFunctionAlignment(2); 1809*0b57cec5SDimitry Andric 1810*0b57cec5SDimitry Andric computeRegisterProperties(Subtarget->getRegisterInfo()); 1811*0b57cec5SDimitry Andric } 1812*0b57cec5SDimitry Andric 1813*0b57cec5SDimitry Andric bool SparcTargetLowering::useSoftFloat() const { 1814*0b57cec5SDimitry Andric return Subtarget->useSoftFloat(); 1815*0b57cec5SDimitry Andric } 1816*0b57cec5SDimitry Andric 1817*0b57cec5SDimitry Andric const char *SparcTargetLowering::getTargetNodeName(unsigned Opcode) const { 1818*0b57cec5SDimitry Andric switch ((SPISD::NodeType)Opcode) { 1819*0b57cec5SDimitry Andric case SPISD::FIRST_NUMBER: break; 1820*0b57cec5SDimitry Andric case SPISD::CMPICC: return "SPISD::CMPICC"; 1821*0b57cec5SDimitry Andric case SPISD::CMPFCC: return "SPISD::CMPFCC"; 1822*0b57cec5SDimitry Andric case SPISD::BRICC: return "SPISD::BRICC"; 1823*0b57cec5SDimitry Andric case SPISD::BRXCC: return "SPISD::BRXCC"; 1824*0b57cec5SDimitry Andric case SPISD::BRFCC: return "SPISD::BRFCC"; 1825*0b57cec5SDimitry Andric case SPISD::SELECT_ICC: return "SPISD::SELECT_ICC"; 1826*0b57cec5SDimitry Andric case SPISD::SELECT_XCC: return "SPISD::SELECT_XCC"; 1827*0b57cec5SDimitry Andric case SPISD::SELECT_FCC: return "SPISD::SELECT_FCC"; 1828*0b57cec5SDimitry Andric case SPISD::Hi: return "SPISD::Hi"; 1829*0b57cec5SDimitry Andric case SPISD::Lo: return "SPISD::Lo"; 1830*0b57cec5SDimitry Andric case SPISD::FTOI: return "SPISD::FTOI"; 1831*0b57cec5SDimitry Andric case SPISD::ITOF: return "SPISD::ITOF"; 1832*0b57cec5SDimitry Andric case SPISD::FTOX: return "SPISD::FTOX"; 1833*0b57cec5SDimitry Andric case SPISD::XTOF: return "SPISD::XTOF"; 1834*0b57cec5SDimitry Andric case SPISD::CALL: return "SPISD::CALL"; 1835*0b57cec5SDimitry Andric case SPISD::RET_FLAG: return "SPISD::RET_FLAG"; 1836*0b57cec5SDimitry Andric case SPISD::GLOBAL_BASE_REG: return "SPISD::GLOBAL_BASE_REG"; 1837*0b57cec5SDimitry Andric case SPISD::FLUSHW: return "SPISD::FLUSHW"; 1838*0b57cec5SDimitry Andric case SPISD::TLS_ADD: return "SPISD::TLS_ADD"; 1839*0b57cec5SDimitry Andric case SPISD::TLS_LD: return "SPISD::TLS_LD"; 1840*0b57cec5SDimitry Andric case SPISD::TLS_CALL: return "SPISD::TLS_CALL"; 1841*0b57cec5SDimitry Andric } 1842*0b57cec5SDimitry Andric return nullptr; 1843*0b57cec5SDimitry Andric } 1844*0b57cec5SDimitry Andric 1845*0b57cec5SDimitry Andric EVT SparcTargetLowering::getSetCCResultType(const DataLayout &, LLVMContext &, 1846*0b57cec5SDimitry Andric EVT VT) const { 1847*0b57cec5SDimitry Andric if (!VT.isVector()) 1848*0b57cec5SDimitry Andric return MVT::i32; 1849*0b57cec5SDimitry Andric return VT.changeVectorElementTypeToInteger(); 1850*0b57cec5SDimitry Andric } 1851*0b57cec5SDimitry Andric 1852*0b57cec5SDimitry Andric /// isMaskedValueZeroForTargetNode - Return true if 'Op & Mask' is known to 1853*0b57cec5SDimitry Andric /// be zero. Op is expected to be a target specific node. Used by DAG 1854*0b57cec5SDimitry Andric /// combiner. 1855*0b57cec5SDimitry Andric void SparcTargetLowering::computeKnownBitsForTargetNode 1856*0b57cec5SDimitry Andric (const SDValue Op, 1857*0b57cec5SDimitry Andric KnownBits &Known, 1858*0b57cec5SDimitry Andric const APInt &DemandedElts, 1859*0b57cec5SDimitry Andric const SelectionDAG &DAG, 1860*0b57cec5SDimitry Andric unsigned Depth) const { 1861*0b57cec5SDimitry Andric KnownBits Known2; 1862*0b57cec5SDimitry Andric Known.resetAll(); 1863*0b57cec5SDimitry Andric 1864*0b57cec5SDimitry Andric switch (Op.getOpcode()) { 1865*0b57cec5SDimitry Andric default: break; 1866*0b57cec5SDimitry Andric case SPISD::SELECT_ICC: 1867*0b57cec5SDimitry Andric case SPISD::SELECT_XCC: 1868*0b57cec5SDimitry Andric case SPISD::SELECT_FCC: 1869*0b57cec5SDimitry Andric Known = DAG.computeKnownBits(Op.getOperand(1), Depth + 1); 1870*0b57cec5SDimitry Andric Known2 = DAG.computeKnownBits(Op.getOperand(0), Depth + 1); 1871*0b57cec5SDimitry Andric 1872*0b57cec5SDimitry Andric // Only known if known in both the LHS and RHS. 1873*0b57cec5SDimitry Andric Known.One &= Known2.One; 1874*0b57cec5SDimitry Andric Known.Zero &= Known2.Zero; 1875*0b57cec5SDimitry Andric break; 1876*0b57cec5SDimitry Andric } 1877*0b57cec5SDimitry Andric } 1878*0b57cec5SDimitry Andric 1879*0b57cec5SDimitry Andric // Look at LHS/RHS/CC and see if they are a lowered setcc instruction. If so 1880*0b57cec5SDimitry Andric // set LHS/RHS and SPCC to the LHS/RHS of the setcc and SPCC to the condition. 1881*0b57cec5SDimitry Andric static void LookThroughSetCC(SDValue &LHS, SDValue &RHS, 1882*0b57cec5SDimitry Andric ISD::CondCode CC, unsigned &SPCC) { 1883*0b57cec5SDimitry Andric if (isNullConstant(RHS) && 1884*0b57cec5SDimitry Andric CC == ISD::SETNE && 1885*0b57cec5SDimitry Andric (((LHS.getOpcode() == SPISD::SELECT_ICC || 1886*0b57cec5SDimitry Andric LHS.getOpcode() == SPISD::SELECT_XCC) && 1887*0b57cec5SDimitry Andric LHS.getOperand(3).getOpcode() == SPISD::CMPICC) || 1888*0b57cec5SDimitry Andric (LHS.getOpcode() == SPISD::SELECT_FCC && 1889*0b57cec5SDimitry Andric LHS.getOperand(3).getOpcode() == SPISD::CMPFCC)) && 1890*0b57cec5SDimitry Andric isOneConstant(LHS.getOperand(0)) && 1891*0b57cec5SDimitry Andric isNullConstant(LHS.getOperand(1))) { 1892*0b57cec5SDimitry Andric SDValue CMPCC = LHS.getOperand(3); 1893*0b57cec5SDimitry Andric SPCC = cast<ConstantSDNode>(LHS.getOperand(2))->getZExtValue(); 1894*0b57cec5SDimitry Andric LHS = CMPCC.getOperand(0); 1895*0b57cec5SDimitry Andric RHS = CMPCC.getOperand(1); 1896*0b57cec5SDimitry Andric } 1897*0b57cec5SDimitry Andric } 1898*0b57cec5SDimitry Andric 1899*0b57cec5SDimitry Andric // Convert to a target node and set target flags. 1900*0b57cec5SDimitry Andric SDValue SparcTargetLowering::withTargetFlags(SDValue Op, unsigned TF, 1901*0b57cec5SDimitry Andric SelectionDAG &DAG) const { 1902*0b57cec5SDimitry Andric if (const GlobalAddressSDNode *GA = dyn_cast<GlobalAddressSDNode>(Op)) 1903*0b57cec5SDimitry Andric return DAG.getTargetGlobalAddress(GA->getGlobal(), 1904*0b57cec5SDimitry Andric SDLoc(GA), 1905*0b57cec5SDimitry Andric GA->getValueType(0), 1906*0b57cec5SDimitry Andric GA->getOffset(), TF); 1907*0b57cec5SDimitry Andric 1908*0b57cec5SDimitry Andric if (const ConstantPoolSDNode *CP = dyn_cast<ConstantPoolSDNode>(Op)) 1909*0b57cec5SDimitry Andric return DAG.getTargetConstantPool(CP->getConstVal(), 1910*0b57cec5SDimitry Andric CP->getValueType(0), 1911*0b57cec5SDimitry Andric CP->getAlignment(), 1912*0b57cec5SDimitry Andric CP->getOffset(), TF); 1913*0b57cec5SDimitry Andric 1914*0b57cec5SDimitry Andric if (const BlockAddressSDNode *BA = dyn_cast<BlockAddressSDNode>(Op)) 1915*0b57cec5SDimitry Andric return DAG.getTargetBlockAddress(BA->getBlockAddress(), 1916*0b57cec5SDimitry Andric Op.getValueType(), 1917*0b57cec5SDimitry Andric 0, 1918*0b57cec5SDimitry Andric TF); 1919*0b57cec5SDimitry Andric 1920*0b57cec5SDimitry Andric if (const ExternalSymbolSDNode *ES = dyn_cast<ExternalSymbolSDNode>(Op)) 1921*0b57cec5SDimitry Andric return DAG.getTargetExternalSymbol(ES->getSymbol(), 1922*0b57cec5SDimitry Andric ES->getValueType(0), TF); 1923*0b57cec5SDimitry Andric 1924*0b57cec5SDimitry Andric llvm_unreachable("Unhandled address SDNode"); 1925*0b57cec5SDimitry Andric } 1926*0b57cec5SDimitry Andric 1927*0b57cec5SDimitry Andric // Split Op into high and low parts according to HiTF and LoTF. 1928*0b57cec5SDimitry Andric // Return an ADD node combining the parts. 1929*0b57cec5SDimitry Andric SDValue SparcTargetLowering::makeHiLoPair(SDValue Op, 1930*0b57cec5SDimitry Andric unsigned HiTF, unsigned LoTF, 1931*0b57cec5SDimitry Andric SelectionDAG &DAG) const { 1932*0b57cec5SDimitry Andric SDLoc DL(Op); 1933*0b57cec5SDimitry Andric EVT VT = Op.getValueType(); 1934*0b57cec5SDimitry Andric SDValue Hi = DAG.getNode(SPISD::Hi, DL, VT, withTargetFlags(Op, HiTF, DAG)); 1935*0b57cec5SDimitry Andric SDValue Lo = DAG.getNode(SPISD::Lo, DL, VT, withTargetFlags(Op, LoTF, DAG)); 1936*0b57cec5SDimitry Andric return DAG.getNode(ISD::ADD, DL, VT, Hi, Lo); 1937*0b57cec5SDimitry Andric } 1938*0b57cec5SDimitry Andric 1939*0b57cec5SDimitry Andric // Build SDNodes for producing an address from a GlobalAddress, ConstantPool, 1940*0b57cec5SDimitry Andric // or ExternalSymbol SDNode. 1941*0b57cec5SDimitry Andric SDValue SparcTargetLowering::makeAddress(SDValue Op, SelectionDAG &DAG) const { 1942*0b57cec5SDimitry Andric SDLoc DL(Op); 1943*0b57cec5SDimitry Andric EVT VT = getPointerTy(DAG.getDataLayout()); 1944*0b57cec5SDimitry Andric 1945*0b57cec5SDimitry Andric // Handle PIC mode first. SPARC needs a got load for every variable! 1946*0b57cec5SDimitry Andric if (isPositionIndependent()) { 1947*0b57cec5SDimitry Andric const Module *M = DAG.getMachineFunction().getFunction().getParent(); 1948*0b57cec5SDimitry Andric PICLevel::Level picLevel = M->getPICLevel(); 1949*0b57cec5SDimitry Andric SDValue Idx; 1950*0b57cec5SDimitry Andric 1951*0b57cec5SDimitry Andric if (picLevel == PICLevel::SmallPIC) { 1952*0b57cec5SDimitry Andric // This is the pic13 code model, the GOT is known to be smaller than 8KiB. 1953*0b57cec5SDimitry Andric Idx = DAG.getNode(SPISD::Lo, DL, Op.getValueType(), 1954*0b57cec5SDimitry Andric withTargetFlags(Op, SparcMCExpr::VK_Sparc_GOT13, DAG)); 1955*0b57cec5SDimitry Andric } else { 1956*0b57cec5SDimitry Andric // This is the pic32 code model, the GOT is known to be smaller than 4GB. 1957*0b57cec5SDimitry Andric Idx = makeHiLoPair(Op, SparcMCExpr::VK_Sparc_GOT22, 1958*0b57cec5SDimitry Andric SparcMCExpr::VK_Sparc_GOT10, DAG); 1959*0b57cec5SDimitry Andric } 1960*0b57cec5SDimitry Andric 1961*0b57cec5SDimitry Andric SDValue GlobalBase = DAG.getNode(SPISD::GLOBAL_BASE_REG, DL, VT); 1962*0b57cec5SDimitry Andric SDValue AbsAddr = DAG.getNode(ISD::ADD, DL, VT, GlobalBase, Idx); 1963*0b57cec5SDimitry Andric // GLOBAL_BASE_REG codegen'ed with call. Inform MFI that this 1964*0b57cec5SDimitry Andric // function has calls. 1965*0b57cec5SDimitry Andric MachineFrameInfo &MFI = DAG.getMachineFunction().getFrameInfo(); 1966*0b57cec5SDimitry Andric MFI.setHasCalls(true); 1967*0b57cec5SDimitry Andric return DAG.getLoad(VT, DL, DAG.getEntryNode(), AbsAddr, 1968*0b57cec5SDimitry Andric MachinePointerInfo::getGOT(DAG.getMachineFunction())); 1969*0b57cec5SDimitry Andric } 1970*0b57cec5SDimitry Andric 1971*0b57cec5SDimitry Andric // This is one of the absolute code models. 1972*0b57cec5SDimitry Andric switch(getTargetMachine().getCodeModel()) { 1973*0b57cec5SDimitry Andric default: 1974*0b57cec5SDimitry Andric llvm_unreachable("Unsupported absolute code model"); 1975*0b57cec5SDimitry Andric case CodeModel::Small: 1976*0b57cec5SDimitry Andric // abs32. 1977*0b57cec5SDimitry Andric return makeHiLoPair(Op, SparcMCExpr::VK_Sparc_HI, 1978*0b57cec5SDimitry Andric SparcMCExpr::VK_Sparc_LO, DAG); 1979*0b57cec5SDimitry Andric case CodeModel::Medium: { 1980*0b57cec5SDimitry Andric // abs44. 1981*0b57cec5SDimitry Andric SDValue H44 = makeHiLoPair(Op, SparcMCExpr::VK_Sparc_H44, 1982*0b57cec5SDimitry Andric SparcMCExpr::VK_Sparc_M44, DAG); 1983*0b57cec5SDimitry Andric H44 = DAG.getNode(ISD::SHL, DL, VT, H44, DAG.getConstant(12, DL, MVT::i32)); 1984*0b57cec5SDimitry Andric SDValue L44 = withTargetFlags(Op, SparcMCExpr::VK_Sparc_L44, DAG); 1985*0b57cec5SDimitry Andric L44 = DAG.getNode(SPISD::Lo, DL, VT, L44); 1986*0b57cec5SDimitry Andric return DAG.getNode(ISD::ADD, DL, VT, H44, L44); 1987*0b57cec5SDimitry Andric } 1988*0b57cec5SDimitry Andric case CodeModel::Large: { 1989*0b57cec5SDimitry Andric // abs64. 1990*0b57cec5SDimitry Andric SDValue Hi = makeHiLoPair(Op, SparcMCExpr::VK_Sparc_HH, 1991*0b57cec5SDimitry Andric SparcMCExpr::VK_Sparc_HM, DAG); 1992*0b57cec5SDimitry Andric Hi = DAG.getNode(ISD::SHL, DL, VT, Hi, DAG.getConstant(32, DL, MVT::i32)); 1993*0b57cec5SDimitry Andric SDValue Lo = makeHiLoPair(Op, SparcMCExpr::VK_Sparc_HI, 1994*0b57cec5SDimitry Andric SparcMCExpr::VK_Sparc_LO, DAG); 1995*0b57cec5SDimitry Andric return DAG.getNode(ISD::ADD, DL, VT, Hi, Lo); 1996*0b57cec5SDimitry Andric } 1997*0b57cec5SDimitry Andric } 1998*0b57cec5SDimitry Andric } 1999*0b57cec5SDimitry Andric 2000*0b57cec5SDimitry Andric SDValue SparcTargetLowering::LowerGlobalAddress(SDValue Op, 2001*0b57cec5SDimitry Andric SelectionDAG &DAG) const { 2002*0b57cec5SDimitry Andric return makeAddress(Op, DAG); 2003*0b57cec5SDimitry Andric } 2004*0b57cec5SDimitry Andric 2005*0b57cec5SDimitry Andric SDValue SparcTargetLowering::LowerConstantPool(SDValue Op, 2006*0b57cec5SDimitry Andric SelectionDAG &DAG) const { 2007*0b57cec5SDimitry Andric return makeAddress(Op, DAG); 2008*0b57cec5SDimitry Andric } 2009*0b57cec5SDimitry Andric 2010*0b57cec5SDimitry Andric SDValue SparcTargetLowering::LowerBlockAddress(SDValue Op, 2011*0b57cec5SDimitry Andric SelectionDAG &DAG) const { 2012*0b57cec5SDimitry Andric return makeAddress(Op, DAG); 2013*0b57cec5SDimitry Andric } 2014*0b57cec5SDimitry Andric 2015*0b57cec5SDimitry Andric SDValue SparcTargetLowering::LowerGlobalTLSAddress(SDValue Op, 2016*0b57cec5SDimitry Andric SelectionDAG &DAG) const { 2017*0b57cec5SDimitry Andric 2018*0b57cec5SDimitry Andric GlobalAddressSDNode *GA = cast<GlobalAddressSDNode>(Op); 2019*0b57cec5SDimitry Andric if (DAG.getTarget().useEmulatedTLS()) 2020*0b57cec5SDimitry Andric return LowerToTLSEmulatedModel(GA, DAG); 2021*0b57cec5SDimitry Andric 2022*0b57cec5SDimitry Andric SDLoc DL(GA); 2023*0b57cec5SDimitry Andric const GlobalValue *GV = GA->getGlobal(); 2024*0b57cec5SDimitry Andric EVT PtrVT = getPointerTy(DAG.getDataLayout()); 2025*0b57cec5SDimitry Andric 2026*0b57cec5SDimitry Andric TLSModel::Model model = getTargetMachine().getTLSModel(GV); 2027*0b57cec5SDimitry Andric 2028*0b57cec5SDimitry Andric if (model == TLSModel::GeneralDynamic || model == TLSModel::LocalDynamic) { 2029*0b57cec5SDimitry Andric unsigned HiTF = ((model == TLSModel::GeneralDynamic) 2030*0b57cec5SDimitry Andric ? SparcMCExpr::VK_Sparc_TLS_GD_HI22 2031*0b57cec5SDimitry Andric : SparcMCExpr::VK_Sparc_TLS_LDM_HI22); 2032*0b57cec5SDimitry Andric unsigned LoTF = ((model == TLSModel::GeneralDynamic) 2033*0b57cec5SDimitry Andric ? SparcMCExpr::VK_Sparc_TLS_GD_LO10 2034*0b57cec5SDimitry Andric : SparcMCExpr::VK_Sparc_TLS_LDM_LO10); 2035*0b57cec5SDimitry Andric unsigned addTF = ((model == TLSModel::GeneralDynamic) 2036*0b57cec5SDimitry Andric ? SparcMCExpr::VK_Sparc_TLS_GD_ADD 2037*0b57cec5SDimitry Andric : SparcMCExpr::VK_Sparc_TLS_LDM_ADD); 2038*0b57cec5SDimitry Andric unsigned callTF = ((model == TLSModel::GeneralDynamic) 2039*0b57cec5SDimitry Andric ? SparcMCExpr::VK_Sparc_TLS_GD_CALL 2040*0b57cec5SDimitry Andric : SparcMCExpr::VK_Sparc_TLS_LDM_CALL); 2041*0b57cec5SDimitry Andric 2042*0b57cec5SDimitry Andric SDValue HiLo = makeHiLoPair(Op, HiTF, LoTF, DAG); 2043*0b57cec5SDimitry Andric SDValue Base = DAG.getNode(SPISD::GLOBAL_BASE_REG, DL, PtrVT); 2044*0b57cec5SDimitry Andric SDValue Argument = DAG.getNode(SPISD::TLS_ADD, DL, PtrVT, Base, HiLo, 2045*0b57cec5SDimitry Andric withTargetFlags(Op, addTF, DAG)); 2046*0b57cec5SDimitry Andric 2047*0b57cec5SDimitry Andric SDValue Chain = DAG.getEntryNode(); 2048*0b57cec5SDimitry Andric SDValue InFlag; 2049*0b57cec5SDimitry Andric 2050*0b57cec5SDimitry Andric Chain = DAG.getCALLSEQ_START(Chain, 1, 0, DL); 2051*0b57cec5SDimitry Andric Chain = DAG.getCopyToReg(Chain, DL, SP::O0, Argument, InFlag); 2052*0b57cec5SDimitry Andric InFlag = Chain.getValue(1); 2053*0b57cec5SDimitry Andric SDValue Callee = DAG.getTargetExternalSymbol("__tls_get_addr", PtrVT); 2054*0b57cec5SDimitry Andric SDValue Symbol = withTargetFlags(Op, callTF, DAG); 2055*0b57cec5SDimitry Andric 2056*0b57cec5SDimitry Andric SDVTList NodeTys = DAG.getVTList(MVT::Other, MVT::Glue); 2057*0b57cec5SDimitry Andric const uint32_t *Mask = Subtarget->getRegisterInfo()->getCallPreservedMask( 2058*0b57cec5SDimitry Andric DAG.getMachineFunction(), CallingConv::C); 2059*0b57cec5SDimitry Andric assert(Mask && "Missing call preserved mask for calling convention"); 2060*0b57cec5SDimitry Andric SDValue Ops[] = {Chain, 2061*0b57cec5SDimitry Andric Callee, 2062*0b57cec5SDimitry Andric Symbol, 2063*0b57cec5SDimitry Andric DAG.getRegister(SP::O0, PtrVT), 2064*0b57cec5SDimitry Andric DAG.getRegisterMask(Mask), 2065*0b57cec5SDimitry Andric InFlag}; 2066*0b57cec5SDimitry Andric Chain = DAG.getNode(SPISD::TLS_CALL, DL, NodeTys, Ops); 2067*0b57cec5SDimitry Andric InFlag = Chain.getValue(1); 2068*0b57cec5SDimitry Andric Chain = DAG.getCALLSEQ_END(Chain, DAG.getIntPtrConstant(1, DL, true), 2069*0b57cec5SDimitry Andric DAG.getIntPtrConstant(0, DL, true), InFlag, DL); 2070*0b57cec5SDimitry Andric InFlag = Chain.getValue(1); 2071*0b57cec5SDimitry Andric SDValue Ret = DAG.getCopyFromReg(Chain, DL, SP::O0, PtrVT, InFlag); 2072*0b57cec5SDimitry Andric 2073*0b57cec5SDimitry Andric if (model != TLSModel::LocalDynamic) 2074*0b57cec5SDimitry Andric return Ret; 2075*0b57cec5SDimitry Andric 2076*0b57cec5SDimitry Andric SDValue Hi = DAG.getNode(SPISD::Hi, DL, PtrVT, 2077*0b57cec5SDimitry Andric withTargetFlags(Op, SparcMCExpr::VK_Sparc_TLS_LDO_HIX22, DAG)); 2078*0b57cec5SDimitry Andric SDValue Lo = DAG.getNode(SPISD::Lo, DL, PtrVT, 2079*0b57cec5SDimitry Andric withTargetFlags(Op, SparcMCExpr::VK_Sparc_TLS_LDO_LOX10, DAG)); 2080*0b57cec5SDimitry Andric HiLo = DAG.getNode(ISD::XOR, DL, PtrVT, Hi, Lo); 2081*0b57cec5SDimitry Andric return DAG.getNode(SPISD::TLS_ADD, DL, PtrVT, Ret, HiLo, 2082*0b57cec5SDimitry Andric withTargetFlags(Op, SparcMCExpr::VK_Sparc_TLS_LDO_ADD, DAG)); 2083*0b57cec5SDimitry Andric } 2084*0b57cec5SDimitry Andric 2085*0b57cec5SDimitry Andric if (model == TLSModel::InitialExec) { 2086*0b57cec5SDimitry Andric unsigned ldTF = ((PtrVT == MVT::i64)? SparcMCExpr::VK_Sparc_TLS_IE_LDX 2087*0b57cec5SDimitry Andric : SparcMCExpr::VK_Sparc_TLS_IE_LD); 2088*0b57cec5SDimitry Andric 2089*0b57cec5SDimitry Andric SDValue Base = DAG.getNode(SPISD::GLOBAL_BASE_REG, DL, PtrVT); 2090*0b57cec5SDimitry Andric 2091*0b57cec5SDimitry Andric // GLOBAL_BASE_REG codegen'ed with call. Inform MFI that this 2092*0b57cec5SDimitry Andric // function has calls. 2093*0b57cec5SDimitry Andric MachineFrameInfo &MFI = DAG.getMachineFunction().getFrameInfo(); 2094*0b57cec5SDimitry Andric MFI.setHasCalls(true); 2095*0b57cec5SDimitry Andric 2096*0b57cec5SDimitry Andric SDValue TGA = makeHiLoPair(Op, 2097*0b57cec5SDimitry Andric SparcMCExpr::VK_Sparc_TLS_IE_HI22, 2098*0b57cec5SDimitry Andric SparcMCExpr::VK_Sparc_TLS_IE_LO10, DAG); 2099*0b57cec5SDimitry Andric SDValue Ptr = DAG.getNode(ISD::ADD, DL, PtrVT, Base, TGA); 2100*0b57cec5SDimitry Andric SDValue Offset = DAG.getNode(SPISD::TLS_LD, 2101*0b57cec5SDimitry Andric DL, PtrVT, Ptr, 2102*0b57cec5SDimitry Andric withTargetFlags(Op, ldTF, DAG)); 2103*0b57cec5SDimitry Andric return DAG.getNode(SPISD::TLS_ADD, DL, PtrVT, 2104*0b57cec5SDimitry Andric DAG.getRegister(SP::G7, PtrVT), Offset, 2105*0b57cec5SDimitry Andric withTargetFlags(Op, 2106*0b57cec5SDimitry Andric SparcMCExpr::VK_Sparc_TLS_IE_ADD, DAG)); 2107*0b57cec5SDimitry Andric } 2108*0b57cec5SDimitry Andric 2109*0b57cec5SDimitry Andric assert(model == TLSModel::LocalExec); 2110*0b57cec5SDimitry Andric SDValue Hi = DAG.getNode(SPISD::Hi, DL, PtrVT, 2111*0b57cec5SDimitry Andric withTargetFlags(Op, SparcMCExpr::VK_Sparc_TLS_LE_HIX22, DAG)); 2112*0b57cec5SDimitry Andric SDValue Lo = DAG.getNode(SPISD::Lo, DL, PtrVT, 2113*0b57cec5SDimitry Andric withTargetFlags(Op, SparcMCExpr::VK_Sparc_TLS_LE_LOX10, DAG)); 2114*0b57cec5SDimitry Andric SDValue Offset = DAG.getNode(ISD::XOR, DL, PtrVT, Hi, Lo); 2115*0b57cec5SDimitry Andric 2116*0b57cec5SDimitry Andric return DAG.getNode(ISD::ADD, DL, PtrVT, 2117*0b57cec5SDimitry Andric DAG.getRegister(SP::G7, PtrVT), Offset); 2118*0b57cec5SDimitry Andric } 2119*0b57cec5SDimitry Andric 2120*0b57cec5SDimitry Andric SDValue SparcTargetLowering::LowerF128_LibCallArg(SDValue Chain, 2121*0b57cec5SDimitry Andric ArgListTy &Args, SDValue Arg, 2122*0b57cec5SDimitry Andric const SDLoc &DL, 2123*0b57cec5SDimitry Andric SelectionDAG &DAG) const { 2124*0b57cec5SDimitry Andric MachineFrameInfo &MFI = DAG.getMachineFunction().getFrameInfo(); 2125*0b57cec5SDimitry Andric EVT ArgVT = Arg.getValueType(); 2126*0b57cec5SDimitry Andric Type *ArgTy = ArgVT.getTypeForEVT(*DAG.getContext()); 2127*0b57cec5SDimitry Andric 2128*0b57cec5SDimitry Andric ArgListEntry Entry; 2129*0b57cec5SDimitry Andric Entry.Node = Arg; 2130*0b57cec5SDimitry Andric Entry.Ty = ArgTy; 2131*0b57cec5SDimitry Andric 2132*0b57cec5SDimitry Andric if (ArgTy->isFP128Ty()) { 2133*0b57cec5SDimitry Andric // Create a stack object and pass the pointer to the library function. 2134*0b57cec5SDimitry Andric int FI = MFI.CreateStackObject(16, 8, false); 2135*0b57cec5SDimitry Andric SDValue FIPtr = DAG.getFrameIndex(FI, getPointerTy(DAG.getDataLayout())); 2136*0b57cec5SDimitry Andric Chain = DAG.getStore(Chain, DL, Entry.Node, FIPtr, MachinePointerInfo(), 2137*0b57cec5SDimitry Andric /* Alignment = */ 8); 2138*0b57cec5SDimitry Andric 2139*0b57cec5SDimitry Andric Entry.Node = FIPtr; 2140*0b57cec5SDimitry Andric Entry.Ty = PointerType::getUnqual(ArgTy); 2141*0b57cec5SDimitry Andric } 2142*0b57cec5SDimitry Andric Args.push_back(Entry); 2143*0b57cec5SDimitry Andric return Chain; 2144*0b57cec5SDimitry Andric } 2145*0b57cec5SDimitry Andric 2146*0b57cec5SDimitry Andric SDValue 2147*0b57cec5SDimitry Andric SparcTargetLowering::LowerF128Op(SDValue Op, SelectionDAG &DAG, 2148*0b57cec5SDimitry Andric const char *LibFuncName, 2149*0b57cec5SDimitry Andric unsigned numArgs) const { 2150*0b57cec5SDimitry Andric 2151*0b57cec5SDimitry Andric ArgListTy Args; 2152*0b57cec5SDimitry Andric 2153*0b57cec5SDimitry Andric MachineFrameInfo &MFI = DAG.getMachineFunction().getFrameInfo(); 2154*0b57cec5SDimitry Andric auto PtrVT = getPointerTy(DAG.getDataLayout()); 2155*0b57cec5SDimitry Andric 2156*0b57cec5SDimitry Andric SDValue Callee = DAG.getExternalSymbol(LibFuncName, PtrVT); 2157*0b57cec5SDimitry Andric Type *RetTy = Op.getValueType().getTypeForEVT(*DAG.getContext()); 2158*0b57cec5SDimitry Andric Type *RetTyABI = RetTy; 2159*0b57cec5SDimitry Andric SDValue Chain = DAG.getEntryNode(); 2160*0b57cec5SDimitry Andric SDValue RetPtr; 2161*0b57cec5SDimitry Andric 2162*0b57cec5SDimitry Andric if (RetTy->isFP128Ty()) { 2163*0b57cec5SDimitry Andric // Create a Stack Object to receive the return value of type f128. 2164*0b57cec5SDimitry Andric ArgListEntry Entry; 2165*0b57cec5SDimitry Andric int RetFI = MFI.CreateStackObject(16, 8, false); 2166*0b57cec5SDimitry Andric RetPtr = DAG.getFrameIndex(RetFI, PtrVT); 2167*0b57cec5SDimitry Andric Entry.Node = RetPtr; 2168*0b57cec5SDimitry Andric Entry.Ty = PointerType::getUnqual(RetTy); 2169*0b57cec5SDimitry Andric if (!Subtarget->is64Bit()) 2170*0b57cec5SDimitry Andric Entry.IsSRet = true; 2171*0b57cec5SDimitry Andric Entry.IsReturned = false; 2172*0b57cec5SDimitry Andric Args.push_back(Entry); 2173*0b57cec5SDimitry Andric RetTyABI = Type::getVoidTy(*DAG.getContext()); 2174*0b57cec5SDimitry Andric } 2175*0b57cec5SDimitry Andric 2176*0b57cec5SDimitry Andric assert(Op->getNumOperands() >= numArgs && "Not enough operands!"); 2177*0b57cec5SDimitry Andric for (unsigned i = 0, e = numArgs; i != e; ++i) { 2178*0b57cec5SDimitry Andric Chain = LowerF128_LibCallArg(Chain, Args, Op.getOperand(i), SDLoc(Op), DAG); 2179*0b57cec5SDimitry Andric } 2180*0b57cec5SDimitry Andric TargetLowering::CallLoweringInfo CLI(DAG); 2181*0b57cec5SDimitry Andric CLI.setDebugLoc(SDLoc(Op)).setChain(Chain) 2182*0b57cec5SDimitry Andric .setCallee(CallingConv::C, RetTyABI, Callee, std::move(Args)); 2183*0b57cec5SDimitry Andric 2184*0b57cec5SDimitry Andric std::pair<SDValue, SDValue> CallInfo = LowerCallTo(CLI); 2185*0b57cec5SDimitry Andric 2186*0b57cec5SDimitry Andric // chain is in second result. 2187*0b57cec5SDimitry Andric if (RetTyABI == RetTy) 2188*0b57cec5SDimitry Andric return CallInfo.first; 2189*0b57cec5SDimitry Andric 2190*0b57cec5SDimitry Andric assert (RetTy->isFP128Ty() && "Unexpected return type!"); 2191*0b57cec5SDimitry Andric 2192*0b57cec5SDimitry Andric Chain = CallInfo.second; 2193*0b57cec5SDimitry Andric 2194*0b57cec5SDimitry Andric // Load RetPtr to get the return value. 2195*0b57cec5SDimitry Andric return DAG.getLoad(Op.getValueType(), SDLoc(Op), Chain, RetPtr, 2196*0b57cec5SDimitry Andric MachinePointerInfo(), /* Alignment = */ 8); 2197*0b57cec5SDimitry Andric } 2198*0b57cec5SDimitry Andric 2199*0b57cec5SDimitry Andric SDValue SparcTargetLowering::LowerF128Compare(SDValue LHS, SDValue RHS, 2200*0b57cec5SDimitry Andric unsigned &SPCC, const SDLoc &DL, 2201*0b57cec5SDimitry Andric SelectionDAG &DAG) const { 2202*0b57cec5SDimitry Andric 2203*0b57cec5SDimitry Andric const char *LibCall = nullptr; 2204*0b57cec5SDimitry Andric bool is64Bit = Subtarget->is64Bit(); 2205*0b57cec5SDimitry Andric switch(SPCC) { 2206*0b57cec5SDimitry Andric default: llvm_unreachable("Unhandled conditional code!"); 2207*0b57cec5SDimitry Andric case SPCC::FCC_E : LibCall = is64Bit? "_Qp_feq" : "_Q_feq"; break; 2208*0b57cec5SDimitry Andric case SPCC::FCC_NE : LibCall = is64Bit? "_Qp_fne" : "_Q_fne"; break; 2209*0b57cec5SDimitry Andric case SPCC::FCC_L : LibCall = is64Bit? "_Qp_flt" : "_Q_flt"; break; 2210*0b57cec5SDimitry Andric case SPCC::FCC_G : LibCall = is64Bit? "_Qp_fgt" : "_Q_fgt"; break; 2211*0b57cec5SDimitry Andric case SPCC::FCC_LE : LibCall = is64Bit? "_Qp_fle" : "_Q_fle"; break; 2212*0b57cec5SDimitry Andric case SPCC::FCC_GE : LibCall = is64Bit? "_Qp_fge" : "_Q_fge"; break; 2213*0b57cec5SDimitry Andric case SPCC::FCC_UL : 2214*0b57cec5SDimitry Andric case SPCC::FCC_ULE: 2215*0b57cec5SDimitry Andric case SPCC::FCC_UG : 2216*0b57cec5SDimitry Andric case SPCC::FCC_UGE: 2217*0b57cec5SDimitry Andric case SPCC::FCC_U : 2218*0b57cec5SDimitry Andric case SPCC::FCC_O : 2219*0b57cec5SDimitry Andric case SPCC::FCC_LG : 2220*0b57cec5SDimitry Andric case SPCC::FCC_UE : LibCall = is64Bit? "_Qp_cmp" : "_Q_cmp"; break; 2221*0b57cec5SDimitry Andric } 2222*0b57cec5SDimitry Andric 2223*0b57cec5SDimitry Andric auto PtrVT = getPointerTy(DAG.getDataLayout()); 2224*0b57cec5SDimitry Andric SDValue Callee = DAG.getExternalSymbol(LibCall, PtrVT); 2225*0b57cec5SDimitry Andric Type *RetTy = Type::getInt32Ty(*DAG.getContext()); 2226*0b57cec5SDimitry Andric ArgListTy Args; 2227*0b57cec5SDimitry Andric SDValue Chain = DAG.getEntryNode(); 2228*0b57cec5SDimitry Andric Chain = LowerF128_LibCallArg(Chain, Args, LHS, DL, DAG); 2229*0b57cec5SDimitry Andric Chain = LowerF128_LibCallArg(Chain, Args, RHS, DL, DAG); 2230*0b57cec5SDimitry Andric 2231*0b57cec5SDimitry Andric TargetLowering::CallLoweringInfo CLI(DAG); 2232*0b57cec5SDimitry Andric CLI.setDebugLoc(DL).setChain(Chain) 2233*0b57cec5SDimitry Andric .setCallee(CallingConv::C, RetTy, Callee, std::move(Args)); 2234*0b57cec5SDimitry Andric 2235*0b57cec5SDimitry Andric std::pair<SDValue, SDValue> CallInfo = LowerCallTo(CLI); 2236*0b57cec5SDimitry Andric 2237*0b57cec5SDimitry Andric // result is in first, and chain is in second result. 2238*0b57cec5SDimitry Andric SDValue Result = CallInfo.first; 2239*0b57cec5SDimitry Andric 2240*0b57cec5SDimitry Andric switch(SPCC) { 2241*0b57cec5SDimitry Andric default: { 2242*0b57cec5SDimitry Andric SDValue RHS = DAG.getTargetConstant(0, DL, Result.getValueType()); 2243*0b57cec5SDimitry Andric SPCC = SPCC::ICC_NE; 2244*0b57cec5SDimitry Andric return DAG.getNode(SPISD::CMPICC, DL, MVT::Glue, Result, RHS); 2245*0b57cec5SDimitry Andric } 2246*0b57cec5SDimitry Andric case SPCC::FCC_UL : { 2247*0b57cec5SDimitry Andric SDValue Mask = DAG.getTargetConstant(1, DL, Result.getValueType()); 2248*0b57cec5SDimitry Andric Result = DAG.getNode(ISD::AND, DL, Result.getValueType(), Result, Mask); 2249*0b57cec5SDimitry Andric SDValue RHS = DAG.getTargetConstant(0, DL, Result.getValueType()); 2250*0b57cec5SDimitry Andric SPCC = SPCC::ICC_NE; 2251*0b57cec5SDimitry Andric return DAG.getNode(SPISD::CMPICC, DL, MVT::Glue, Result, RHS); 2252*0b57cec5SDimitry Andric } 2253*0b57cec5SDimitry Andric case SPCC::FCC_ULE: { 2254*0b57cec5SDimitry Andric SDValue RHS = DAG.getTargetConstant(2, DL, Result.getValueType()); 2255*0b57cec5SDimitry Andric SPCC = SPCC::ICC_NE; 2256*0b57cec5SDimitry Andric return DAG.getNode(SPISD::CMPICC, DL, MVT::Glue, Result, RHS); 2257*0b57cec5SDimitry Andric } 2258*0b57cec5SDimitry Andric case SPCC::FCC_UG : { 2259*0b57cec5SDimitry Andric SDValue RHS = DAG.getTargetConstant(1, DL, Result.getValueType()); 2260*0b57cec5SDimitry Andric SPCC = SPCC::ICC_G; 2261*0b57cec5SDimitry Andric return DAG.getNode(SPISD::CMPICC, DL, MVT::Glue, Result, RHS); 2262*0b57cec5SDimitry Andric } 2263*0b57cec5SDimitry Andric case SPCC::FCC_UGE: { 2264*0b57cec5SDimitry Andric SDValue RHS = DAG.getTargetConstant(1, DL, Result.getValueType()); 2265*0b57cec5SDimitry Andric SPCC = SPCC::ICC_NE; 2266*0b57cec5SDimitry Andric return DAG.getNode(SPISD::CMPICC, DL, MVT::Glue, Result, RHS); 2267*0b57cec5SDimitry Andric } 2268*0b57cec5SDimitry Andric 2269*0b57cec5SDimitry Andric case SPCC::FCC_U : { 2270*0b57cec5SDimitry Andric SDValue RHS = DAG.getTargetConstant(3, DL, Result.getValueType()); 2271*0b57cec5SDimitry Andric SPCC = SPCC::ICC_E; 2272*0b57cec5SDimitry Andric return DAG.getNode(SPISD::CMPICC, DL, MVT::Glue, Result, RHS); 2273*0b57cec5SDimitry Andric } 2274*0b57cec5SDimitry Andric case SPCC::FCC_O : { 2275*0b57cec5SDimitry Andric SDValue RHS = DAG.getTargetConstant(3, DL, Result.getValueType()); 2276*0b57cec5SDimitry Andric SPCC = SPCC::ICC_NE; 2277*0b57cec5SDimitry Andric return DAG.getNode(SPISD::CMPICC, DL, MVT::Glue, Result, RHS); 2278*0b57cec5SDimitry Andric } 2279*0b57cec5SDimitry Andric case SPCC::FCC_LG : { 2280*0b57cec5SDimitry Andric SDValue Mask = DAG.getTargetConstant(3, DL, Result.getValueType()); 2281*0b57cec5SDimitry Andric Result = DAG.getNode(ISD::AND, DL, Result.getValueType(), Result, Mask); 2282*0b57cec5SDimitry Andric SDValue RHS = DAG.getTargetConstant(0, DL, Result.getValueType()); 2283*0b57cec5SDimitry Andric SPCC = SPCC::ICC_NE; 2284*0b57cec5SDimitry Andric return DAG.getNode(SPISD::CMPICC, DL, MVT::Glue, Result, RHS); 2285*0b57cec5SDimitry Andric } 2286*0b57cec5SDimitry Andric case SPCC::FCC_UE : { 2287*0b57cec5SDimitry Andric SDValue Mask = DAG.getTargetConstant(3, DL, Result.getValueType()); 2288*0b57cec5SDimitry Andric Result = DAG.getNode(ISD::AND, DL, Result.getValueType(), Result, Mask); 2289*0b57cec5SDimitry Andric SDValue RHS = DAG.getTargetConstant(0, DL, Result.getValueType()); 2290*0b57cec5SDimitry Andric SPCC = SPCC::ICC_E; 2291*0b57cec5SDimitry Andric return DAG.getNode(SPISD::CMPICC, DL, MVT::Glue, Result, RHS); 2292*0b57cec5SDimitry Andric } 2293*0b57cec5SDimitry Andric } 2294*0b57cec5SDimitry Andric } 2295*0b57cec5SDimitry Andric 2296*0b57cec5SDimitry Andric static SDValue 2297*0b57cec5SDimitry Andric LowerF128_FPEXTEND(SDValue Op, SelectionDAG &DAG, 2298*0b57cec5SDimitry Andric const SparcTargetLowering &TLI) { 2299*0b57cec5SDimitry Andric 2300*0b57cec5SDimitry Andric if (Op.getOperand(0).getValueType() == MVT::f64) 2301*0b57cec5SDimitry Andric return TLI.LowerF128Op(Op, DAG, 2302*0b57cec5SDimitry Andric TLI.getLibcallName(RTLIB::FPEXT_F64_F128), 1); 2303*0b57cec5SDimitry Andric 2304*0b57cec5SDimitry Andric if (Op.getOperand(0).getValueType() == MVT::f32) 2305*0b57cec5SDimitry Andric return TLI.LowerF128Op(Op, DAG, 2306*0b57cec5SDimitry Andric TLI.getLibcallName(RTLIB::FPEXT_F32_F128), 1); 2307*0b57cec5SDimitry Andric 2308*0b57cec5SDimitry Andric llvm_unreachable("fpextend with non-float operand!"); 2309*0b57cec5SDimitry Andric return SDValue(); 2310*0b57cec5SDimitry Andric } 2311*0b57cec5SDimitry Andric 2312*0b57cec5SDimitry Andric static SDValue 2313*0b57cec5SDimitry Andric LowerF128_FPROUND(SDValue Op, SelectionDAG &DAG, 2314*0b57cec5SDimitry Andric const SparcTargetLowering &TLI) { 2315*0b57cec5SDimitry Andric // FP_ROUND on f64 and f32 are legal. 2316*0b57cec5SDimitry Andric if (Op.getOperand(0).getValueType() != MVT::f128) 2317*0b57cec5SDimitry Andric return Op; 2318*0b57cec5SDimitry Andric 2319*0b57cec5SDimitry Andric if (Op.getValueType() == MVT::f64) 2320*0b57cec5SDimitry Andric return TLI.LowerF128Op(Op, DAG, 2321*0b57cec5SDimitry Andric TLI.getLibcallName(RTLIB::FPROUND_F128_F64), 1); 2322*0b57cec5SDimitry Andric if (Op.getValueType() == MVT::f32) 2323*0b57cec5SDimitry Andric return TLI.LowerF128Op(Op, DAG, 2324*0b57cec5SDimitry Andric TLI.getLibcallName(RTLIB::FPROUND_F128_F32), 1); 2325*0b57cec5SDimitry Andric 2326*0b57cec5SDimitry Andric llvm_unreachable("fpround to non-float!"); 2327*0b57cec5SDimitry Andric return SDValue(); 2328*0b57cec5SDimitry Andric } 2329*0b57cec5SDimitry Andric 2330*0b57cec5SDimitry Andric static SDValue LowerFP_TO_SINT(SDValue Op, SelectionDAG &DAG, 2331*0b57cec5SDimitry Andric const SparcTargetLowering &TLI, 2332*0b57cec5SDimitry Andric bool hasHardQuad) { 2333*0b57cec5SDimitry Andric SDLoc dl(Op); 2334*0b57cec5SDimitry Andric EVT VT = Op.getValueType(); 2335*0b57cec5SDimitry Andric assert(VT == MVT::i32 || VT == MVT::i64); 2336*0b57cec5SDimitry Andric 2337*0b57cec5SDimitry Andric // Expand f128 operations to fp128 abi calls. 2338*0b57cec5SDimitry Andric if (Op.getOperand(0).getValueType() == MVT::f128 2339*0b57cec5SDimitry Andric && (!hasHardQuad || !TLI.isTypeLegal(VT))) { 2340*0b57cec5SDimitry Andric const char *libName = TLI.getLibcallName(VT == MVT::i32 2341*0b57cec5SDimitry Andric ? RTLIB::FPTOSINT_F128_I32 2342*0b57cec5SDimitry Andric : RTLIB::FPTOSINT_F128_I64); 2343*0b57cec5SDimitry Andric return TLI.LowerF128Op(Op, DAG, libName, 1); 2344*0b57cec5SDimitry Andric } 2345*0b57cec5SDimitry Andric 2346*0b57cec5SDimitry Andric // Expand if the resulting type is illegal. 2347*0b57cec5SDimitry Andric if (!TLI.isTypeLegal(VT)) 2348*0b57cec5SDimitry Andric return SDValue(); 2349*0b57cec5SDimitry Andric 2350*0b57cec5SDimitry Andric // Otherwise, Convert the fp value to integer in an FP register. 2351*0b57cec5SDimitry Andric if (VT == MVT::i32) 2352*0b57cec5SDimitry Andric Op = DAG.getNode(SPISD::FTOI, dl, MVT::f32, Op.getOperand(0)); 2353*0b57cec5SDimitry Andric else 2354*0b57cec5SDimitry Andric Op = DAG.getNode(SPISD::FTOX, dl, MVT::f64, Op.getOperand(0)); 2355*0b57cec5SDimitry Andric 2356*0b57cec5SDimitry Andric return DAG.getNode(ISD::BITCAST, dl, VT, Op); 2357*0b57cec5SDimitry Andric } 2358*0b57cec5SDimitry Andric 2359*0b57cec5SDimitry Andric static SDValue LowerSINT_TO_FP(SDValue Op, SelectionDAG &DAG, 2360*0b57cec5SDimitry Andric const SparcTargetLowering &TLI, 2361*0b57cec5SDimitry Andric bool hasHardQuad) { 2362*0b57cec5SDimitry Andric SDLoc dl(Op); 2363*0b57cec5SDimitry Andric EVT OpVT = Op.getOperand(0).getValueType(); 2364*0b57cec5SDimitry Andric assert(OpVT == MVT::i32 || (OpVT == MVT::i64)); 2365*0b57cec5SDimitry Andric 2366*0b57cec5SDimitry Andric EVT floatVT = (OpVT == MVT::i32) ? MVT::f32 : MVT::f64; 2367*0b57cec5SDimitry Andric 2368*0b57cec5SDimitry Andric // Expand f128 operations to fp128 ABI calls. 2369*0b57cec5SDimitry Andric if (Op.getValueType() == MVT::f128 2370*0b57cec5SDimitry Andric && (!hasHardQuad || !TLI.isTypeLegal(OpVT))) { 2371*0b57cec5SDimitry Andric const char *libName = TLI.getLibcallName(OpVT == MVT::i32 2372*0b57cec5SDimitry Andric ? RTLIB::SINTTOFP_I32_F128 2373*0b57cec5SDimitry Andric : RTLIB::SINTTOFP_I64_F128); 2374*0b57cec5SDimitry Andric return TLI.LowerF128Op(Op, DAG, libName, 1); 2375*0b57cec5SDimitry Andric } 2376*0b57cec5SDimitry Andric 2377*0b57cec5SDimitry Andric // Expand if the operand type is illegal. 2378*0b57cec5SDimitry Andric if (!TLI.isTypeLegal(OpVT)) 2379*0b57cec5SDimitry Andric return SDValue(); 2380*0b57cec5SDimitry Andric 2381*0b57cec5SDimitry Andric // Otherwise, Convert the int value to FP in an FP register. 2382*0b57cec5SDimitry Andric SDValue Tmp = DAG.getNode(ISD::BITCAST, dl, floatVT, Op.getOperand(0)); 2383*0b57cec5SDimitry Andric unsigned opcode = (OpVT == MVT::i32)? SPISD::ITOF : SPISD::XTOF; 2384*0b57cec5SDimitry Andric return DAG.getNode(opcode, dl, Op.getValueType(), Tmp); 2385*0b57cec5SDimitry Andric } 2386*0b57cec5SDimitry Andric 2387*0b57cec5SDimitry Andric static SDValue LowerFP_TO_UINT(SDValue Op, SelectionDAG &DAG, 2388*0b57cec5SDimitry Andric const SparcTargetLowering &TLI, 2389*0b57cec5SDimitry Andric bool hasHardQuad) { 2390*0b57cec5SDimitry Andric SDLoc dl(Op); 2391*0b57cec5SDimitry Andric EVT VT = Op.getValueType(); 2392*0b57cec5SDimitry Andric 2393*0b57cec5SDimitry Andric // Expand if it does not involve f128 or the target has support for 2394*0b57cec5SDimitry Andric // quad floating point instructions and the resulting type is legal. 2395*0b57cec5SDimitry Andric if (Op.getOperand(0).getValueType() != MVT::f128 || 2396*0b57cec5SDimitry Andric (hasHardQuad && TLI.isTypeLegal(VT))) 2397*0b57cec5SDimitry Andric return SDValue(); 2398*0b57cec5SDimitry Andric 2399*0b57cec5SDimitry Andric assert(VT == MVT::i32 || VT == MVT::i64); 2400*0b57cec5SDimitry Andric 2401*0b57cec5SDimitry Andric return TLI.LowerF128Op(Op, DAG, 2402*0b57cec5SDimitry Andric TLI.getLibcallName(VT == MVT::i32 2403*0b57cec5SDimitry Andric ? RTLIB::FPTOUINT_F128_I32 2404*0b57cec5SDimitry Andric : RTLIB::FPTOUINT_F128_I64), 2405*0b57cec5SDimitry Andric 1); 2406*0b57cec5SDimitry Andric } 2407*0b57cec5SDimitry Andric 2408*0b57cec5SDimitry Andric static SDValue LowerUINT_TO_FP(SDValue Op, SelectionDAG &DAG, 2409*0b57cec5SDimitry Andric const SparcTargetLowering &TLI, 2410*0b57cec5SDimitry Andric bool hasHardQuad) { 2411*0b57cec5SDimitry Andric SDLoc dl(Op); 2412*0b57cec5SDimitry Andric EVT OpVT = Op.getOperand(0).getValueType(); 2413*0b57cec5SDimitry Andric assert(OpVT == MVT::i32 || OpVT == MVT::i64); 2414*0b57cec5SDimitry Andric 2415*0b57cec5SDimitry Andric // Expand if it does not involve f128 or the target has support for 2416*0b57cec5SDimitry Andric // quad floating point instructions and the operand type is legal. 2417*0b57cec5SDimitry Andric if (Op.getValueType() != MVT::f128 || (hasHardQuad && TLI.isTypeLegal(OpVT))) 2418*0b57cec5SDimitry Andric return SDValue(); 2419*0b57cec5SDimitry Andric 2420*0b57cec5SDimitry Andric return TLI.LowerF128Op(Op, DAG, 2421*0b57cec5SDimitry Andric TLI.getLibcallName(OpVT == MVT::i32 2422*0b57cec5SDimitry Andric ? RTLIB::UINTTOFP_I32_F128 2423*0b57cec5SDimitry Andric : RTLIB::UINTTOFP_I64_F128), 2424*0b57cec5SDimitry Andric 1); 2425*0b57cec5SDimitry Andric } 2426*0b57cec5SDimitry Andric 2427*0b57cec5SDimitry Andric static SDValue LowerBR_CC(SDValue Op, SelectionDAG &DAG, 2428*0b57cec5SDimitry Andric const SparcTargetLowering &TLI, 2429*0b57cec5SDimitry Andric bool hasHardQuad) { 2430*0b57cec5SDimitry Andric SDValue Chain = Op.getOperand(0); 2431*0b57cec5SDimitry Andric ISD::CondCode CC = cast<CondCodeSDNode>(Op.getOperand(1))->get(); 2432*0b57cec5SDimitry Andric SDValue LHS = Op.getOperand(2); 2433*0b57cec5SDimitry Andric SDValue RHS = Op.getOperand(3); 2434*0b57cec5SDimitry Andric SDValue Dest = Op.getOperand(4); 2435*0b57cec5SDimitry Andric SDLoc dl(Op); 2436*0b57cec5SDimitry Andric unsigned Opc, SPCC = ~0U; 2437*0b57cec5SDimitry Andric 2438*0b57cec5SDimitry Andric // If this is a br_cc of a "setcc", and if the setcc got lowered into 2439*0b57cec5SDimitry Andric // an CMP[IF]CC/SELECT_[IF]CC pair, find the original compared values. 2440*0b57cec5SDimitry Andric LookThroughSetCC(LHS, RHS, CC, SPCC); 2441*0b57cec5SDimitry Andric 2442*0b57cec5SDimitry Andric // Get the condition flag. 2443*0b57cec5SDimitry Andric SDValue CompareFlag; 2444*0b57cec5SDimitry Andric if (LHS.getValueType().isInteger()) { 2445*0b57cec5SDimitry Andric CompareFlag = DAG.getNode(SPISD::CMPICC, dl, MVT::Glue, LHS, RHS); 2446*0b57cec5SDimitry Andric if (SPCC == ~0U) SPCC = IntCondCCodeToICC(CC); 2447*0b57cec5SDimitry Andric // 32-bit compares use the icc flags, 64-bit uses the xcc flags. 2448*0b57cec5SDimitry Andric Opc = LHS.getValueType() == MVT::i32 ? SPISD::BRICC : SPISD::BRXCC; 2449*0b57cec5SDimitry Andric } else { 2450*0b57cec5SDimitry Andric if (!hasHardQuad && LHS.getValueType() == MVT::f128) { 2451*0b57cec5SDimitry Andric if (SPCC == ~0U) SPCC = FPCondCCodeToFCC(CC); 2452*0b57cec5SDimitry Andric CompareFlag = TLI.LowerF128Compare(LHS, RHS, SPCC, dl, DAG); 2453*0b57cec5SDimitry Andric Opc = SPISD::BRICC; 2454*0b57cec5SDimitry Andric } else { 2455*0b57cec5SDimitry Andric CompareFlag = DAG.getNode(SPISD::CMPFCC, dl, MVT::Glue, LHS, RHS); 2456*0b57cec5SDimitry Andric if (SPCC == ~0U) SPCC = FPCondCCodeToFCC(CC); 2457*0b57cec5SDimitry Andric Opc = SPISD::BRFCC; 2458*0b57cec5SDimitry Andric } 2459*0b57cec5SDimitry Andric } 2460*0b57cec5SDimitry Andric return DAG.getNode(Opc, dl, MVT::Other, Chain, Dest, 2461*0b57cec5SDimitry Andric DAG.getConstant(SPCC, dl, MVT::i32), CompareFlag); 2462*0b57cec5SDimitry Andric } 2463*0b57cec5SDimitry Andric 2464*0b57cec5SDimitry Andric static SDValue LowerSELECT_CC(SDValue Op, SelectionDAG &DAG, 2465*0b57cec5SDimitry Andric const SparcTargetLowering &TLI, 2466*0b57cec5SDimitry Andric bool hasHardQuad) { 2467*0b57cec5SDimitry Andric SDValue LHS = Op.getOperand(0); 2468*0b57cec5SDimitry Andric SDValue RHS = Op.getOperand(1); 2469*0b57cec5SDimitry Andric ISD::CondCode CC = cast<CondCodeSDNode>(Op.getOperand(4))->get(); 2470*0b57cec5SDimitry Andric SDValue TrueVal = Op.getOperand(2); 2471*0b57cec5SDimitry Andric SDValue FalseVal = Op.getOperand(3); 2472*0b57cec5SDimitry Andric SDLoc dl(Op); 2473*0b57cec5SDimitry Andric unsigned Opc, SPCC = ~0U; 2474*0b57cec5SDimitry Andric 2475*0b57cec5SDimitry Andric // If this is a select_cc of a "setcc", and if the setcc got lowered into 2476*0b57cec5SDimitry Andric // an CMP[IF]CC/SELECT_[IF]CC pair, find the original compared values. 2477*0b57cec5SDimitry Andric LookThroughSetCC(LHS, RHS, CC, SPCC); 2478*0b57cec5SDimitry Andric 2479*0b57cec5SDimitry Andric SDValue CompareFlag; 2480*0b57cec5SDimitry Andric if (LHS.getValueType().isInteger()) { 2481*0b57cec5SDimitry Andric CompareFlag = DAG.getNode(SPISD::CMPICC, dl, MVT::Glue, LHS, RHS); 2482*0b57cec5SDimitry Andric Opc = LHS.getValueType() == MVT::i32 ? 2483*0b57cec5SDimitry Andric SPISD::SELECT_ICC : SPISD::SELECT_XCC; 2484*0b57cec5SDimitry Andric if (SPCC == ~0U) SPCC = IntCondCCodeToICC(CC); 2485*0b57cec5SDimitry Andric } else { 2486*0b57cec5SDimitry Andric if (!hasHardQuad && LHS.getValueType() == MVT::f128) { 2487*0b57cec5SDimitry Andric if (SPCC == ~0U) SPCC = FPCondCCodeToFCC(CC); 2488*0b57cec5SDimitry Andric CompareFlag = TLI.LowerF128Compare(LHS, RHS, SPCC, dl, DAG); 2489*0b57cec5SDimitry Andric Opc = SPISD::SELECT_ICC; 2490*0b57cec5SDimitry Andric } else { 2491*0b57cec5SDimitry Andric CompareFlag = DAG.getNode(SPISD::CMPFCC, dl, MVT::Glue, LHS, RHS); 2492*0b57cec5SDimitry Andric Opc = SPISD::SELECT_FCC; 2493*0b57cec5SDimitry Andric if (SPCC == ~0U) SPCC = FPCondCCodeToFCC(CC); 2494*0b57cec5SDimitry Andric } 2495*0b57cec5SDimitry Andric } 2496*0b57cec5SDimitry Andric return DAG.getNode(Opc, dl, TrueVal.getValueType(), TrueVal, FalseVal, 2497*0b57cec5SDimitry Andric DAG.getConstant(SPCC, dl, MVT::i32), CompareFlag); 2498*0b57cec5SDimitry Andric } 2499*0b57cec5SDimitry Andric 2500*0b57cec5SDimitry Andric static SDValue LowerVASTART(SDValue Op, SelectionDAG &DAG, 2501*0b57cec5SDimitry Andric const SparcTargetLowering &TLI) { 2502*0b57cec5SDimitry Andric MachineFunction &MF = DAG.getMachineFunction(); 2503*0b57cec5SDimitry Andric SparcMachineFunctionInfo *FuncInfo = MF.getInfo<SparcMachineFunctionInfo>(); 2504*0b57cec5SDimitry Andric auto PtrVT = TLI.getPointerTy(DAG.getDataLayout()); 2505*0b57cec5SDimitry Andric 2506*0b57cec5SDimitry Andric // Need frame address to find the address of VarArgsFrameIndex. 2507*0b57cec5SDimitry Andric MF.getFrameInfo().setFrameAddressIsTaken(true); 2508*0b57cec5SDimitry Andric 2509*0b57cec5SDimitry Andric // vastart just stores the address of the VarArgsFrameIndex slot into the 2510*0b57cec5SDimitry Andric // memory location argument. 2511*0b57cec5SDimitry Andric SDLoc DL(Op); 2512*0b57cec5SDimitry Andric SDValue Offset = 2513*0b57cec5SDimitry Andric DAG.getNode(ISD::ADD, DL, PtrVT, DAG.getRegister(SP::I6, PtrVT), 2514*0b57cec5SDimitry Andric DAG.getIntPtrConstant(FuncInfo->getVarArgsFrameOffset(), DL)); 2515*0b57cec5SDimitry Andric const Value *SV = cast<SrcValueSDNode>(Op.getOperand(2))->getValue(); 2516*0b57cec5SDimitry Andric return DAG.getStore(Op.getOperand(0), DL, Offset, Op.getOperand(1), 2517*0b57cec5SDimitry Andric MachinePointerInfo(SV)); 2518*0b57cec5SDimitry Andric } 2519*0b57cec5SDimitry Andric 2520*0b57cec5SDimitry Andric static SDValue LowerVAARG(SDValue Op, SelectionDAG &DAG) { 2521*0b57cec5SDimitry Andric SDNode *Node = Op.getNode(); 2522*0b57cec5SDimitry Andric EVT VT = Node->getValueType(0); 2523*0b57cec5SDimitry Andric SDValue InChain = Node->getOperand(0); 2524*0b57cec5SDimitry Andric SDValue VAListPtr = Node->getOperand(1); 2525*0b57cec5SDimitry Andric EVT PtrVT = VAListPtr.getValueType(); 2526*0b57cec5SDimitry Andric const Value *SV = cast<SrcValueSDNode>(Node->getOperand(2))->getValue(); 2527*0b57cec5SDimitry Andric SDLoc DL(Node); 2528*0b57cec5SDimitry Andric SDValue VAList = 2529*0b57cec5SDimitry Andric DAG.getLoad(PtrVT, DL, InChain, VAListPtr, MachinePointerInfo(SV)); 2530*0b57cec5SDimitry Andric // Increment the pointer, VAList, to the next vaarg. 2531*0b57cec5SDimitry Andric SDValue NextPtr = DAG.getNode(ISD::ADD, DL, PtrVT, VAList, 2532*0b57cec5SDimitry Andric DAG.getIntPtrConstant(VT.getSizeInBits()/8, 2533*0b57cec5SDimitry Andric DL)); 2534*0b57cec5SDimitry Andric // Store the incremented VAList to the legalized pointer. 2535*0b57cec5SDimitry Andric InChain = DAG.getStore(VAList.getValue(1), DL, NextPtr, VAListPtr, 2536*0b57cec5SDimitry Andric MachinePointerInfo(SV)); 2537*0b57cec5SDimitry Andric // Load the actual argument out of the pointer VAList. 2538*0b57cec5SDimitry Andric // We can't count on greater alignment than the word size. 2539*0b57cec5SDimitry Andric return DAG.getLoad(VT, DL, InChain, VAList, MachinePointerInfo(), 2540*0b57cec5SDimitry Andric std::min(PtrVT.getSizeInBits(), VT.getSizeInBits()) / 8); 2541*0b57cec5SDimitry Andric } 2542*0b57cec5SDimitry Andric 2543*0b57cec5SDimitry Andric static SDValue LowerDYNAMIC_STACKALLOC(SDValue Op, SelectionDAG &DAG, 2544*0b57cec5SDimitry Andric const SparcSubtarget *Subtarget) { 2545*0b57cec5SDimitry Andric SDValue Chain = Op.getOperand(0); // Legalize the chain. 2546*0b57cec5SDimitry Andric SDValue Size = Op.getOperand(1); // Legalize the size. 2547*0b57cec5SDimitry Andric unsigned Align = cast<ConstantSDNode>(Op.getOperand(2))->getZExtValue(); 2548*0b57cec5SDimitry Andric unsigned StackAlign = Subtarget->getFrameLowering()->getStackAlignment(); 2549*0b57cec5SDimitry Andric EVT VT = Size->getValueType(0); 2550*0b57cec5SDimitry Andric SDLoc dl(Op); 2551*0b57cec5SDimitry Andric 2552*0b57cec5SDimitry Andric // TODO: implement over-aligned alloca. (Note: also implies 2553*0b57cec5SDimitry Andric // supporting support for overaligned function frames + dynamic 2554*0b57cec5SDimitry Andric // allocations, at all, which currently isn't supported) 2555*0b57cec5SDimitry Andric if (Align > StackAlign) { 2556*0b57cec5SDimitry Andric const MachineFunction &MF = DAG.getMachineFunction(); 2557*0b57cec5SDimitry Andric report_fatal_error("Function \"" + Twine(MF.getName()) + "\": " 2558*0b57cec5SDimitry Andric "over-aligned dynamic alloca not supported."); 2559*0b57cec5SDimitry Andric } 2560*0b57cec5SDimitry Andric 2561*0b57cec5SDimitry Andric // The resultant pointer needs to be above the register spill area 2562*0b57cec5SDimitry Andric // at the bottom of the stack. 2563*0b57cec5SDimitry Andric unsigned regSpillArea; 2564*0b57cec5SDimitry Andric if (Subtarget->is64Bit()) { 2565*0b57cec5SDimitry Andric regSpillArea = 128; 2566*0b57cec5SDimitry Andric } else { 2567*0b57cec5SDimitry Andric // On Sparc32, the size of the spill area is 92. Unfortunately, 2568*0b57cec5SDimitry Andric // that's only 4-byte aligned, not 8-byte aligned (the stack 2569*0b57cec5SDimitry Andric // pointer is 8-byte aligned). So, if the user asked for an 8-byte 2570*0b57cec5SDimitry Andric // aligned dynamic allocation, we actually need to add 96 to the 2571*0b57cec5SDimitry Andric // bottom of the stack, instead of 92, to ensure 8-byte alignment. 2572*0b57cec5SDimitry Andric 2573*0b57cec5SDimitry Andric // That also means adding 4 to the size of the allocation -- 2574*0b57cec5SDimitry Andric // before applying the 8-byte rounding. Unfortunately, we the 2575*0b57cec5SDimitry Andric // value we get here has already had rounding applied. So, we need 2576*0b57cec5SDimitry Andric // to add 8, instead, wasting a bit more memory. 2577*0b57cec5SDimitry Andric 2578*0b57cec5SDimitry Andric // Further, this only actually needs to be done if the required 2579*0b57cec5SDimitry Andric // alignment is > 4, but, we've lost that info by this point, too, 2580*0b57cec5SDimitry Andric // so we always apply it. 2581*0b57cec5SDimitry Andric 2582*0b57cec5SDimitry Andric // (An alternative approach would be to always reserve 96 bytes 2583*0b57cec5SDimitry Andric // instead of the required 92, but then we'd waste 4 extra bytes 2584*0b57cec5SDimitry Andric // in every frame, not just those with dynamic stack allocations) 2585*0b57cec5SDimitry Andric 2586*0b57cec5SDimitry Andric // TODO: modify code in SelectionDAGBuilder to make this less sad. 2587*0b57cec5SDimitry Andric 2588*0b57cec5SDimitry Andric Size = DAG.getNode(ISD::ADD, dl, VT, Size, 2589*0b57cec5SDimitry Andric DAG.getConstant(8, dl, VT)); 2590*0b57cec5SDimitry Andric regSpillArea = 96; 2591*0b57cec5SDimitry Andric } 2592*0b57cec5SDimitry Andric 2593*0b57cec5SDimitry Andric unsigned SPReg = SP::O6; 2594*0b57cec5SDimitry Andric SDValue SP = DAG.getCopyFromReg(Chain, dl, SPReg, VT); 2595*0b57cec5SDimitry Andric SDValue NewSP = DAG.getNode(ISD::SUB, dl, VT, SP, Size); // Value 2596*0b57cec5SDimitry Andric Chain = DAG.getCopyToReg(SP.getValue(1), dl, SPReg, NewSP); // Output chain 2597*0b57cec5SDimitry Andric 2598*0b57cec5SDimitry Andric regSpillArea += Subtarget->getStackPointerBias(); 2599*0b57cec5SDimitry Andric 2600*0b57cec5SDimitry Andric SDValue NewVal = DAG.getNode(ISD::ADD, dl, VT, NewSP, 2601*0b57cec5SDimitry Andric DAG.getConstant(regSpillArea, dl, VT)); 2602*0b57cec5SDimitry Andric SDValue Ops[2] = { NewVal, Chain }; 2603*0b57cec5SDimitry Andric return DAG.getMergeValues(Ops, dl); 2604*0b57cec5SDimitry Andric } 2605*0b57cec5SDimitry Andric 2606*0b57cec5SDimitry Andric 2607*0b57cec5SDimitry Andric static SDValue getFLUSHW(SDValue Op, SelectionDAG &DAG) { 2608*0b57cec5SDimitry Andric SDLoc dl(Op); 2609*0b57cec5SDimitry Andric SDValue Chain = DAG.getNode(SPISD::FLUSHW, 2610*0b57cec5SDimitry Andric dl, MVT::Other, DAG.getEntryNode()); 2611*0b57cec5SDimitry Andric return Chain; 2612*0b57cec5SDimitry Andric } 2613*0b57cec5SDimitry Andric 2614*0b57cec5SDimitry Andric static SDValue getFRAMEADDR(uint64_t depth, SDValue Op, SelectionDAG &DAG, 2615*0b57cec5SDimitry Andric const SparcSubtarget *Subtarget, 2616*0b57cec5SDimitry Andric bool AlwaysFlush = false) { 2617*0b57cec5SDimitry Andric MachineFrameInfo &MFI = DAG.getMachineFunction().getFrameInfo(); 2618*0b57cec5SDimitry Andric MFI.setFrameAddressIsTaken(true); 2619*0b57cec5SDimitry Andric 2620*0b57cec5SDimitry Andric EVT VT = Op.getValueType(); 2621*0b57cec5SDimitry Andric SDLoc dl(Op); 2622*0b57cec5SDimitry Andric unsigned FrameReg = SP::I6; 2623*0b57cec5SDimitry Andric unsigned stackBias = Subtarget->getStackPointerBias(); 2624*0b57cec5SDimitry Andric 2625*0b57cec5SDimitry Andric SDValue FrameAddr; 2626*0b57cec5SDimitry Andric SDValue Chain; 2627*0b57cec5SDimitry Andric 2628*0b57cec5SDimitry Andric // flush first to make sure the windowed registers' values are in stack 2629*0b57cec5SDimitry Andric Chain = (depth || AlwaysFlush) ? getFLUSHW(Op, DAG) : DAG.getEntryNode(); 2630*0b57cec5SDimitry Andric 2631*0b57cec5SDimitry Andric FrameAddr = DAG.getCopyFromReg(Chain, dl, FrameReg, VT); 2632*0b57cec5SDimitry Andric 2633*0b57cec5SDimitry Andric unsigned Offset = (Subtarget->is64Bit()) ? (stackBias + 112) : 56; 2634*0b57cec5SDimitry Andric 2635*0b57cec5SDimitry Andric while (depth--) { 2636*0b57cec5SDimitry Andric SDValue Ptr = DAG.getNode(ISD::ADD, dl, VT, FrameAddr, 2637*0b57cec5SDimitry Andric DAG.getIntPtrConstant(Offset, dl)); 2638*0b57cec5SDimitry Andric FrameAddr = DAG.getLoad(VT, dl, Chain, Ptr, MachinePointerInfo()); 2639*0b57cec5SDimitry Andric } 2640*0b57cec5SDimitry Andric if (Subtarget->is64Bit()) 2641*0b57cec5SDimitry Andric FrameAddr = DAG.getNode(ISD::ADD, dl, VT, FrameAddr, 2642*0b57cec5SDimitry Andric DAG.getIntPtrConstant(stackBias, dl)); 2643*0b57cec5SDimitry Andric return FrameAddr; 2644*0b57cec5SDimitry Andric } 2645*0b57cec5SDimitry Andric 2646*0b57cec5SDimitry Andric 2647*0b57cec5SDimitry Andric static SDValue LowerFRAMEADDR(SDValue Op, SelectionDAG &DAG, 2648*0b57cec5SDimitry Andric const SparcSubtarget *Subtarget) { 2649*0b57cec5SDimitry Andric 2650*0b57cec5SDimitry Andric uint64_t depth = Op.getConstantOperandVal(0); 2651*0b57cec5SDimitry Andric 2652*0b57cec5SDimitry Andric return getFRAMEADDR(depth, Op, DAG, Subtarget); 2653*0b57cec5SDimitry Andric 2654*0b57cec5SDimitry Andric } 2655*0b57cec5SDimitry Andric 2656*0b57cec5SDimitry Andric static SDValue LowerRETURNADDR(SDValue Op, SelectionDAG &DAG, 2657*0b57cec5SDimitry Andric const SparcTargetLowering &TLI, 2658*0b57cec5SDimitry Andric const SparcSubtarget *Subtarget) { 2659*0b57cec5SDimitry Andric MachineFunction &MF = DAG.getMachineFunction(); 2660*0b57cec5SDimitry Andric MachineFrameInfo &MFI = MF.getFrameInfo(); 2661*0b57cec5SDimitry Andric MFI.setReturnAddressIsTaken(true); 2662*0b57cec5SDimitry Andric 2663*0b57cec5SDimitry Andric if (TLI.verifyReturnAddressArgumentIsConstant(Op, DAG)) 2664*0b57cec5SDimitry Andric return SDValue(); 2665*0b57cec5SDimitry Andric 2666*0b57cec5SDimitry Andric EVT VT = Op.getValueType(); 2667*0b57cec5SDimitry Andric SDLoc dl(Op); 2668*0b57cec5SDimitry Andric uint64_t depth = Op.getConstantOperandVal(0); 2669*0b57cec5SDimitry Andric 2670*0b57cec5SDimitry Andric SDValue RetAddr; 2671*0b57cec5SDimitry Andric if (depth == 0) { 2672*0b57cec5SDimitry Andric auto PtrVT = TLI.getPointerTy(DAG.getDataLayout()); 2673*0b57cec5SDimitry Andric unsigned RetReg = MF.addLiveIn(SP::I7, TLI.getRegClassFor(PtrVT)); 2674*0b57cec5SDimitry Andric RetAddr = DAG.getCopyFromReg(DAG.getEntryNode(), dl, RetReg, VT); 2675*0b57cec5SDimitry Andric return RetAddr; 2676*0b57cec5SDimitry Andric } 2677*0b57cec5SDimitry Andric 2678*0b57cec5SDimitry Andric // Need frame address to find return address of the caller. 2679*0b57cec5SDimitry Andric SDValue FrameAddr = getFRAMEADDR(depth - 1, Op, DAG, Subtarget, true); 2680*0b57cec5SDimitry Andric 2681*0b57cec5SDimitry Andric unsigned Offset = (Subtarget->is64Bit()) ? 120 : 60; 2682*0b57cec5SDimitry Andric SDValue Ptr = DAG.getNode(ISD::ADD, 2683*0b57cec5SDimitry Andric dl, VT, 2684*0b57cec5SDimitry Andric FrameAddr, 2685*0b57cec5SDimitry Andric DAG.getIntPtrConstant(Offset, dl)); 2686*0b57cec5SDimitry Andric RetAddr = DAG.getLoad(VT, dl, DAG.getEntryNode(), Ptr, MachinePointerInfo()); 2687*0b57cec5SDimitry Andric 2688*0b57cec5SDimitry Andric return RetAddr; 2689*0b57cec5SDimitry Andric } 2690*0b57cec5SDimitry Andric 2691*0b57cec5SDimitry Andric static SDValue LowerF64Op(SDValue SrcReg64, const SDLoc &dl, SelectionDAG &DAG, 2692*0b57cec5SDimitry Andric unsigned opcode) { 2693*0b57cec5SDimitry Andric assert(SrcReg64.getValueType() == MVT::f64 && "LowerF64Op called on non-double!"); 2694*0b57cec5SDimitry Andric assert(opcode == ISD::FNEG || opcode == ISD::FABS); 2695*0b57cec5SDimitry Andric 2696*0b57cec5SDimitry Andric // Lower fneg/fabs on f64 to fneg/fabs on f32. 2697*0b57cec5SDimitry Andric // fneg f64 => fneg f32:sub_even, fmov f32:sub_odd. 2698*0b57cec5SDimitry Andric // fabs f64 => fabs f32:sub_even, fmov f32:sub_odd. 2699*0b57cec5SDimitry Andric 2700*0b57cec5SDimitry Andric // Note: in little-endian, the floating-point value is stored in the 2701*0b57cec5SDimitry Andric // registers are in the opposite order, so the subreg with the sign 2702*0b57cec5SDimitry Andric // bit is the highest-numbered (odd), rather than the 2703*0b57cec5SDimitry Andric // lowest-numbered (even). 2704*0b57cec5SDimitry Andric 2705*0b57cec5SDimitry Andric SDValue Hi32 = DAG.getTargetExtractSubreg(SP::sub_even, dl, MVT::f32, 2706*0b57cec5SDimitry Andric SrcReg64); 2707*0b57cec5SDimitry Andric SDValue Lo32 = DAG.getTargetExtractSubreg(SP::sub_odd, dl, MVT::f32, 2708*0b57cec5SDimitry Andric SrcReg64); 2709*0b57cec5SDimitry Andric 2710*0b57cec5SDimitry Andric if (DAG.getDataLayout().isLittleEndian()) 2711*0b57cec5SDimitry Andric Lo32 = DAG.getNode(opcode, dl, MVT::f32, Lo32); 2712*0b57cec5SDimitry Andric else 2713*0b57cec5SDimitry Andric Hi32 = DAG.getNode(opcode, dl, MVT::f32, Hi32); 2714*0b57cec5SDimitry Andric 2715*0b57cec5SDimitry Andric SDValue DstReg64 = SDValue(DAG.getMachineNode(TargetOpcode::IMPLICIT_DEF, 2716*0b57cec5SDimitry Andric dl, MVT::f64), 0); 2717*0b57cec5SDimitry Andric DstReg64 = DAG.getTargetInsertSubreg(SP::sub_even, dl, MVT::f64, 2718*0b57cec5SDimitry Andric DstReg64, Hi32); 2719*0b57cec5SDimitry Andric DstReg64 = DAG.getTargetInsertSubreg(SP::sub_odd, dl, MVT::f64, 2720*0b57cec5SDimitry Andric DstReg64, Lo32); 2721*0b57cec5SDimitry Andric return DstReg64; 2722*0b57cec5SDimitry Andric } 2723*0b57cec5SDimitry Andric 2724*0b57cec5SDimitry Andric // Lower a f128 load into two f64 loads. 2725*0b57cec5SDimitry Andric static SDValue LowerF128Load(SDValue Op, SelectionDAG &DAG) 2726*0b57cec5SDimitry Andric { 2727*0b57cec5SDimitry Andric SDLoc dl(Op); 2728*0b57cec5SDimitry Andric LoadSDNode *LdNode = dyn_cast<LoadSDNode>(Op.getNode()); 2729*0b57cec5SDimitry Andric assert(LdNode && LdNode->getOffset().isUndef() 2730*0b57cec5SDimitry Andric && "Unexpected node type"); 2731*0b57cec5SDimitry Andric 2732*0b57cec5SDimitry Andric unsigned alignment = LdNode->getAlignment(); 2733*0b57cec5SDimitry Andric if (alignment > 8) 2734*0b57cec5SDimitry Andric alignment = 8; 2735*0b57cec5SDimitry Andric 2736*0b57cec5SDimitry Andric SDValue Hi64 = 2737*0b57cec5SDimitry Andric DAG.getLoad(MVT::f64, dl, LdNode->getChain(), LdNode->getBasePtr(), 2738*0b57cec5SDimitry Andric LdNode->getPointerInfo(), alignment); 2739*0b57cec5SDimitry Andric EVT addrVT = LdNode->getBasePtr().getValueType(); 2740*0b57cec5SDimitry Andric SDValue LoPtr = DAG.getNode(ISD::ADD, dl, addrVT, 2741*0b57cec5SDimitry Andric LdNode->getBasePtr(), 2742*0b57cec5SDimitry Andric DAG.getConstant(8, dl, addrVT)); 2743*0b57cec5SDimitry Andric SDValue Lo64 = DAG.getLoad(MVT::f64, dl, LdNode->getChain(), LoPtr, 2744*0b57cec5SDimitry Andric LdNode->getPointerInfo(), alignment); 2745*0b57cec5SDimitry Andric 2746*0b57cec5SDimitry Andric SDValue SubRegEven = DAG.getTargetConstant(SP::sub_even64, dl, MVT::i32); 2747*0b57cec5SDimitry Andric SDValue SubRegOdd = DAG.getTargetConstant(SP::sub_odd64, dl, MVT::i32); 2748*0b57cec5SDimitry Andric 2749*0b57cec5SDimitry Andric SDNode *InFP128 = DAG.getMachineNode(TargetOpcode::IMPLICIT_DEF, 2750*0b57cec5SDimitry Andric dl, MVT::f128); 2751*0b57cec5SDimitry Andric InFP128 = DAG.getMachineNode(TargetOpcode::INSERT_SUBREG, dl, 2752*0b57cec5SDimitry Andric MVT::f128, 2753*0b57cec5SDimitry Andric SDValue(InFP128, 0), 2754*0b57cec5SDimitry Andric Hi64, 2755*0b57cec5SDimitry Andric SubRegEven); 2756*0b57cec5SDimitry Andric InFP128 = DAG.getMachineNode(TargetOpcode::INSERT_SUBREG, dl, 2757*0b57cec5SDimitry Andric MVT::f128, 2758*0b57cec5SDimitry Andric SDValue(InFP128, 0), 2759*0b57cec5SDimitry Andric Lo64, 2760*0b57cec5SDimitry Andric SubRegOdd); 2761*0b57cec5SDimitry Andric SDValue OutChains[2] = { SDValue(Hi64.getNode(), 1), 2762*0b57cec5SDimitry Andric SDValue(Lo64.getNode(), 1) }; 2763*0b57cec5SDimitry Andric SDValue OutChain = DAG.getNode(ISD::TokenFactor, dl, MVT::Other, OutChains); 2764*0b57cec5SDimitry Andric SDValue Ops[2] = {SDValue(InFP128,0), OutChain}; 2765*0b57cec5SDimitry Andric return DAG.getMergeValues(Ops, dl); 2766*0b57cec5SDimitry Andric } 2767*0b57cec5SDimitry Andric 2768*0b57cec5SDimitry Andric static SDValue LowerLOAD(SDValue Op, SelectionDAG &DAG) 2769*0b57cec5SDimitry Andric { 2770*0b57cec5SDimitry Andric LoadSDNode *LdNode = cast<LoadSDNode>(Op.getNode()); 2771*0b57cec5SDimitry Andric 2772*0b57cec5SDimitry Andric EVT MemVT = LdNode->getMemoryVT(); 2773*0b57cec5SDimitry Andric if (MemVT == MVT::f128) 2774*0b57cec5SDimitry Andric return LowerF128Load(Op, DAG); 2775*0b57cec5SDimitry Andric 2776*0b57cec5SDimitry Andric return Op; 2777*0b57cec5SDimitry Andric } 2778*0b57cec5SDimitry Andric 2779*0b57cec5SDimitry Andric // Lower a f128 store into two f64 stores. 2780*0b57cec5SDimitry Andric static SDValue LowerF128Store(SDValue Op, SelectionDAG &DAG) { 2781*0b57cec5SDimitry Andric SDLoc dl(Op); 2782*0b57cec5SDimitry Andric StoreSDNode *StNode = dyn_cast<StoreSDNode>(Op.getNode()); 2783*0b57cec5SDimitry Andric assert(StNode && StNode->getOffset().isUndef() 2784*0b57cec5SDimitry Andric && "Unexpected node type"); 2785*0b57cec5SDimitry Andric SDValue SubRegEven = DAG.getTargetConstant(SP::sub_even64, dl, MVT::i32); 2786*0b57cec5SDimitry Andric SDValue SubRegOdd = DAG.getTargetConstant(SP::sub_odd64, dl, MVT::i32); 2787*0b57cec5SDimitry Andric 2788*0b57cec5SDimitry Andric SDNode *Hi64 = DAG.getMachineNode(TargetOpcode::EXTRACT_SUBREG, 2789*0b57cec5SDimitry Andric dl, 2790*0b57cec5SDimitry Andric MVT::f64, 2791*0b57cec5SDimitry Andric StNode->getValue(), 2792*0b57cec5SDimitry Andric SubRegEven); 2793*0b57cec5SDimitry Andric SDNode *Lo64 = DAG.getMachineNode(TargetOpcode::EXTRACT_SUBREG, 2794*0b57cec5SDimitry Andric dl, 2795*0b57cec5SDimitry Andric MVT::f64, 2796*0b57cec5SDimitry Andric StNode->getValue(), 2797*0b57cec5SDimitry Andric SubRegOdd); 2798*0b57cec5SDimitry Andric 2799*0b57cec5SDimitry Andric unsigned alignment = StNode->getAlignment(); 2800*0b57cec5SDimitry Andric if (alignment > 8) 2801*0b57cec5SDimitry Andric alignment = 8; 2802*0b57cec5SDimitry Andric 2803*0b57cec5SDimitry Andric SDValue OutChains[2]; 2804*0b57cec5SDimitry Andric OutChains[0] = 2805*0b57cec5SDimitry Andric DAG.getStore(StNode->getChain(), dl, SDValue(Hi64, 0), 2806*0b57cec5SDimitry Andric StNode->getBasePtr(), MachinePointerInfo(), alignment); 2807*0b57cec5SDimitry Andric EVT addrVT = StNode->getBasePtr().getValueType(); 2808*0b57cec5SDimitry Andric SDValue LoPtr = DAG.getNode(ISD::ADD, dl, addrVT, 2809*0b57cec5SDimitry Andric StNode->getBasePtr(), 2810*0b57cec5SDimitry Andric DAG.getConstant(8, dl, addrVT)); 2811*0b57cec5SDimitry Andric OutChains[1] = DAG.getStore(StNode->getChain(), dl, SDValue(Lo64, 0), LoPtr, 2812*0b57cec5SDimitry Andric MachinePointerInfo(), alignment); 2813*0b57cec5SDimitry Andric return DAG.getNode(ISD::TokenFactor, dl, MVT::Other, OutChains); 2814*0b57cec5SDimitry Andric } 2815*0b57cec5SDimitry Andric 2816*0b57cec5SDimitry Andric static SDValue LowerSTORE(SDValue Op, SelectionDAG &DAG) 2817*0b57cec5SDimitry Andric { 2818*0b57cec5SDimitry Andric SDLoc dl(Op); 2819*0b57cec5SDimitry Andric StoreSDNode *St = cast<StoreSDNode>(Op.getNode()); 2820*0b57cec5SDimitry Andric 2821*0b57cec5SDimitry Andric EVT MemVT = St->getMemoryVT(); 2822*0b57cec5SDimitry Andric if (MemVT == MVT::f128) 2823*0b57cec5SDimitry Andric return LowerF128Store(Op, DAG); 2824*0b57cec5SDimitry Andric 2825*0b57cec5SDimitry Andric if (MemVT == MVT::i64) { 2826*0b57cec5SDimitry Andric // Custom handling for i64 stores: turn it into a bitcast and a 2827*0b57cec5SDimitry Andric // v2i32 store. 2828*0b57cec5SDimitry Andric SDValue Val = DAG.getNode(ISD::BITCAST, dl, MVT::v2i32, St->getValue()); 2829*0b57cec5SDimitry Andric SDValue Chain = DAG.getStore( 2830*0b57cec5SDimitry Andric St->getChain(), dl, Val, St->getBasePtr(), St->getPointerInfo(), 2831*0b57cec5SDimitry Andric St->getAlignment(), St->getMemOperand()->getFlags(), St->getAAInfo()); 2832*0b57cec5SDimitry Andric return Chain; 2833*0b57cec5SDimitry Andric } 2834*0b57cec5SDimitry Andric 2835*0b57cec5SDimitry Andric return SDValue(); 2836*0b57cec5SDimitry Andric } 2837*0b57cec5SDimitry Andric 2838*0b57cec5SDimitry Andric static SDValue LowerFNEGorFABS(SDValue Op, SelectionDAG &DAG, bool isV9) { 2839*0b57cec5SDimitry Andric assert((Op.getOpcode() == ISD::FNEG || Op.getOpcode() == ISD::FABS) 2840*0b57cec5SDimitry Andric && "invalid opcode"); 2841*0b57cec5SDimitry Andric 2842*0b57cec5SDimitry Andric SDLoc dl(Op); 2843*0b57cec5SDimitry Andric 2844*0b57cec5SDimitry Andric if (Op.getValueType() == MVT::f64) 2845*0b57cec5SDimitry Andric return LowerF64Op(Op.getOperand(0), dl, DAG, Op.getOpcode()); 2846*0b57cec5SDimitry Andric if (Op.getValueType() != MVT::f128) 2847*0b57cec5SDimitry Andric return Op; 2848*0b57cec5SDimitry Andric 2849*0b57cec5SDimitry Andric // Lower fabs/fneg on f128 to fabs/fneg on f64 2850*0b57cec5SDimitry Andric // fabs/fneg f128 => fabs/fneg f64:sub_even64, fmov f64:sub_odd64 2851*0b57cec5SDimitry Andric // (As with LowerF64Op, on little-endian, we need to negate the odd 2852*0b57cec5SDimitry Andric // subreg) 2853*0b57cec5SDimitry Andric 2854*0b57cec5SDimitry Andric SDValue SrcReg128 = Op.getOperand(0); 2855*0b57cec5SDimitry Andric SDValue Hi64 = DAG.getTargetExtractSubreg(SP::sub_even64, dl, MVT::f64, 2856*0b57cec5SDimitry Andric SrcReg128); 2857*0b57cec5SDimitry Andric SDValue Lo64 = DAG.getTargetExtractSubreg(SP::sub_odd64, dl, MVT::f64, 2858*0b57cec5SDimitry Andric SrcReg128); 2859*0b57cec5SDimitry Andric 2860*0b57cec5SDimitry Andric if (DAG.getDataLayout().isLittleEndian()) { 2861*0b57cec5SDimitry Andric if (isV9) 2862*0b57cec5SDimitry Andric Lo64 = DAG.getNode(Op.getOpcode(), dl, MVT::f64, Lo64); 2863*0b57cec5SDimitry Andric else 2864*0b57cec5SDimitry Andric Lo64 = LowerF64Op(Lo64, dl, DAG, Op.getOpcode()); 2865*0b57cec5SDimitry Andric } else { 2866*0b57cec5SDimitry Andric if (isV9) 2867*0b57cec5SDimitry Andric Hi64 = DAG.getNode(Op.getOpcode(), dl, MVT::f64, Hi64); 2868*0b57cec5SDimitry Andric else 2869*0b57cec5SDimitry Andric Hi64 = LowerF64Op(Hi64, dl, DAG, Op.getOpcode()); 2870*0b57cec5SDimitry Andric } 2871*0b57cec5SDimitry Andric 2872*0b57cec5SDimitry Andric SDValue DstReg128 = SDValue(DAG.getMachineNode(TargetOpcode::IMPLICIT_DEF, 2873*0b57cec5SDimitry Andric dl, MVT::f128), 0); 2874*0b57cec5SDimitry Andric DstReg128 = DAG.getTargetInsertSubreg(SP::sub_even64, dl, MVT::f128, 2875*0b57cec5SDimitry Andric DstReg128, Hi64); 2876*0b57cec5SDimitry Andric DstReg128 = DAG.getTargetInsertSubreg(SP::sub_odd64, dl, MVT::f128, 2877*0b57cec5SDimitry Andric DstReg128, Lo64); 2878*0b57cec5SDimitry Andric return DstReg128; 2879*0b57cec5SDimitry Andric } 2880*0b57cec5SDimitry Andric 2881*0b57cec5SDimitry Andric static SDValue LowerADDC_ADDE_SUBC_SUBE(SDValue Op, SelectionDAG &DAG) { 2882*0b57cec5SDimitry Andric 2883*0b57cec5SDimitry Andric if (Op.getValueType() != MVT::i64) 2884*0b57cec5SDimitry Andric return Op; 2885*0b57cec5SDimitry Andric 2886*0b57cec5SDimitry Andric SDLoc dl(Op); 2887*0b57cec5SDimitry Andric SDValue Src1 = Op.getOperand(0); 2888*0b57cec5SDimitry Andric SDValue Src1Lo = DAG.getNode(ISD::TRUNCATE, dl, MVT::i32, Src1); 2889*0b57cec5SDimitry Andric SDValue Src1Hi = DAG.getNode(ISD::SRL, dl, MVT::i64, Src1, 2890*0b57cec5SDimitry Andric DAG.getConstant(32, dl, MVT::i64)); 2891*0b57cec5SDimitry Andric Src1Hi = DAG.getNode(ISD::TRUNCATE, dl, MVT::i32, Src1Hi); 2892*0b57cec5SDimitry Andric 2893*0b57cec5SDimitry Andric SDValue Src2 = Op.getOperand(1); 2894*0b57cec5SDimitry Andric SDValue Src2Lo = DAG.getNode(ISD::TRUNCATE, dl, MVT::i32, Src2); 2895*0b57cec5SDimitry Andric SDValue Src2Hi = DAG.getNode(ISD::SRL, dl, MVT::i64, Src2, 2896*0b57cec5SDimitry Andric DAG.getConstant(32, dl, MVT::i64)); 2897*0b57cec5SDimitry Andric Src2Hi = DAG.getNode(ISD::TRUNCATE, dl, MVT::i32, Src2Hi); 2898*0b57cec5SDimitry Andric 2899*0b57cec5SDimitry Andric 2900*0b57cec5SDimitry Andric bool hasChain = false; 2901*0b57cec5SDimitry Andric unsigned hiOpc = Op.getOpcode(); 2902*0b57cec5SDimitry Andric switch (Op.getOpcode()) { 2903*0b57cec5SDimitry Andric default: llvm_unreachable("Invalid opcode"); 2904*0b57cec5SDimitry Andric case ISD::ADDC: hiOpc = ISD::ADDE; break; 2905*0b57cec5SDimitry Andric case ISD::ADDE: hasChain = true; break; 2906*0b57cec5SDimitry Andric case ISD::SUBC: hiOpc = ISD::SUBE; break; 2907*0b57cec5SDimitry Andric case ISD::SUBE: hasChain = true; break; 2908*0b57cec5SDimitry Andric } 2909*0b57cec5SDimitry Andric SDValue Lo; 2910*0b57cec5SDimitry Andric SDVTList VTs = DAG.getVTList(MVT::i32, MVT::Glue); 2911*0b57cec5SDimitry Andric if (hasChain) { 2912*0b57cec5SDimitry Andric Lo = DAG.getNode(Op.getOpcode(), dl, VTs, Src1Lo, Src2Lo, 2913*0b57cec5SDimitry Andric Op.getOperand(2)); 2914*0b57cec5SDimitry Andric } else { 2915*0b57cec5SDimitry Andric Lo = DAG.getNode(Op.getOpcode(), dl, VTs, Src1Lo, Src2Lo); 2916*0b57cec5SDimitry Andric } 2917*0b57cec5SDimitry Andric SDValue Hi = DAG.getNode(hiOpc, dl, VTs, Src1Hi, Src2Hi, Lo.getValue(1)); 2918*0b57cec5SDimitry Andric SDValue Carry = Hi.getValue(1); 2919*0b57cec5SDimitry Andric 2920*0b57cec5SDimitry Andric Lo = DAG.getNode(ISD::ZERO_EXTEND, dl, MVT::i64, Lo); 2921*0b57cec5SDimitry Andric Hi = DAG.getNode(ISD::ZERO_EXTEND, dl, MVT::i64, Hi); 2922*0b57cec5SDimitry Andric Hi = DAG.getNode(ISD::SHL, dl, MVT::i64, Hi, 2923*0b57cec5SDimitry Andric DAG.getConstant(32, dl, MVT::i64)); 2924*0b57cec5SDimitry Andric 2925*0b57cec5SDimitry Andric SDValue Dst = DAG.getNode(ISD::OR, dl, MVT::i64, Hi, Lo); 2926*0b57cec5SDimitry Andric SDValue Ops[2] = { Dst, Carry }; 2927*0b57cec5SDimitry Andric return DAG.getMergeValues(Ops, dl); 2928*0b57cec5SDimitry Andric } 2929*0b57cec5SDimitry Andric 2930*0b57cec5SDimitry Andric // Custom lower UMULO/SMULO for SPARC. This code is similar to ExpandNode() 2931*0b57cec5SDimitry Andric // in LegalizeDAG.cpp except the order of arguments to the library function. 2932*0b57cec5SDimitry Andric static SDValue LowerUMULO_SMULO(SDValue Op, SelectionDAG &DAG, 2933*0b57cec5SDimitry Andric const SparcTargetLowering &TLI) 2934*0b57cec5SDimitry Andric { 2935*0b57cec5SDimitry Andric unsigned opcode = Op.getOpcode(); 2936*0b57cec5SDimitry Andric assert((opcode == ISD::UMULO || opcode == ISD::SMULO) && "Invalid Opcode."); 2937*0b57cec5SDimitry Andric 2938*0b57cec5SDimitry Andric bool isSigned = (opcode == ISD::SMULO); 2939*0b57cec5SDimitry Andric EVT VT = MVT::i64; 2940*0b57cec5SDimitry Andric EVT WideVT = MVT::i128; 2941*0b57cec5SDimitry Andric SDLoc dl(Op); 2942*0b57cec5SDimitry Andric SDValue LHS = Op.getOperand(0); 2943*0b57cec5SDimitry Andric 2944*0b57cec5SDimitry Andric if (LHS.getValueType() != VT) 2945*0b57cec5SDimitry Andric return Op; 2946*0b57cec5SDimitry Andric 2947*0b57cec5SDimitry Andric SDValue ShiftAmt = DAG.getConstant(63, dl, VT); 2948*0b57cec5SDimitry Andric 2949*0b57cec5SDimitry Andric SDValue RHS = Op.getOperand(1); 2950*0b57cec5SDimitry Andric SDValue HiLHS = DAG.getNode(ISD::SRA, dl, VT, LHS, ShiftAmt); 2951*0b57cec5SDimitry Andric SDValue HiRHS = DAG.getNode(ISD::SRA, dl, MVT::i64, RHS, ShiftAmt); 2952*0b57cec5SDimitry Andric SDValue Args[] = { HiLHS, LHS, HiRHS, RHS }; 2953*0b57cec5SDimitry Andric 2954*0b57cec5SDimitry Andric SDValue MulResult = TLI.makeLibCall(DAG, 2955*0b57cec5SDimitry Andric RTLIB::MUL_I128, WideVT, 2956*0b57cec5SDimitry Andric Args, isSigned, dl).first; 2957*0b57cec5SDimitry Andric SDValue BottomHalf = DAG.getNode(ISD::EXTRACT_ELEMENT, dl, VT, 2958*0b57cec5SDimitry Andric MulResult, DAG.getIntPtrConstant(0, dl)); 2959*0b57cec5SDimitry Andric SDValue TopHalf = DAG.getNode(ISD::EXTRACT_ELEMENT, dl, VT, 2960*0b57cec5SDimitry Andric MulResult, DAG.getIntPtrConstant(1, dl)); 2961*0b57cec5SDimitry Andric if (isSigned) { 2962*0b57cec5SDimitry Andric SDValue Tmp1 = DAG.getNode(ISD::SRA, dl, VT, BottomHalf, ShiftAmt); 2963*0b57cec5SDimitry Andric TopHalf = DAG.getSetCC(dl, MVT::i32, TopHalf, Tmp1, ISD::SETNE); 2964*0b57cec5SDimitry Andric } else { 2965*0b57cec5SDimitry Andric TopHalf = DAG.getSetCC(dl, MVT::i32, TopHalf, DAG.getConstant(0, dl, VT), 2966*0b57cec5SDimitry Andric ISD::SETNE); 2967*0b57cec5SDimitry Andric } 2968*0b57cec5SDimitry Andric // MulResult is a node with an illegal type. Because such things are not 2969*0b57cec5SDimitry Andric // generally permitted during this phase of legalization, ensure that 2970*0b57cec5SDimitry Andric // nothing is left using the node. The above EXTRACT_ELEMENT nodes should have 2971*0b57cec5SDimitry Andric // been folded. 2972*0b57cec5SDimitry Andric assert(MulResult->use_empty() && "Illegally typed node still in use!"); 2973*0b57cec5SDimitry Andric 2974*0b57cec5SDimitry Andric SDValue Ops[2] = { BottomHalf, TopHalf } ; 2975*0b57cec5SDimitry Andric return DAG.getMergeValues(Ops, dl); 2976*0b57cec5SDimitry Andric } 2977*0b57cec5SDimitry Andric 2978*0b57cec5SDimitry Andric static SDValue LowerATOMIC_LOAD_STORE(SDValue Op, SelectionDAG &DAG) { 2979*0b57cec5SDimitry Andric if (isStrongerThanMonotonic(cast<AtomicSDNode>(Op)->getOrdering())) 2980*0b57cec5SDimitry Andric // Expand with a fence. 2981*0b57cec5SDimitry Andric return SDValue(); 2982*0b57cec5SDimitry Andric 2983*0b57cec5SDimitry Andric // Monotonic load/stores are legal. 2984*0b57cec5SDimitry Andric return Op; 2985*0b57cec5SDimitry Andric } 2986*0b57cec5SDimitry Andric 2987*0b57cec5SDimitry Andric SDValue SparcTargetLowering::LowerINTRINSIC_WO_CHAIN(SDValue Op, 2988*0b57cec5SDimitry Andric SelectionDAG &DAG) const { 2989*0b57cec5SDimitry Andric unsigned IntNo = cast<ConstantSDNode>(Op.getOperand(0))->getZExtValue(); 2990*0b57cec5SDimitry Andric SDLoc dl(Op); 2991*0b57cec5SDimitry Andric switch (IntNo) { 2992*0b57cec5SDimitry Andric default: return SDValue(); // Don't custom lower most intrinsics. 2993*0b57cec5SDimitry Andric case Intrinsic::thread_pointer: { 2994*0b57cec5SDimitry Andric EVT PtrVT = getPointerTy(DAG.getDataLayout()); 2995*0b57cec5SDimitry Andric return DAG.getRegister(SP::G7, PtrVT); 2996*0b57cec5SDimitry Andric } 2997*0b57cec5SDimitry Andric } 2998*0b57cec5SDimitry Andric } 2999*0b57cec5SDimitry Andric 3000*0b57cec5SDimitry Andric SDValue SparcTargetLowering:: 3001*0b57cec5SDimitry Andric LowerOperation(SDValue Op, SelectionDAG &DAG) const { 3002*0b57cec5SDimitry Andric 3003*0b57cec5SDimitry Andric bool hasHardQuad = Subtarget->hasHardQuad(); 3004*0b57cec5SDimitry Andric bool isV9 = Subtarget->isV9(); 3005*0b57cec5SDimitry Andric 3006*0b57cec5SDimitry Andric switch (Op.getOpcode()) { 3007*0b57cec5SDimitry Andric default: llvm_unreachable("Should not custom lower this!"); 3008*0b57cec5SDimitry Andric 3009*0b57cec5SDimitry Andric case ISD::RETURNADDR: return LowerRETURNADDR(Op, DAG, *this, 3010*0b57cec5SDimitry Andric Subtarget); 3011*0b57cec5SDimitry Andric case ISD::FRAMEADDR: return LowerFRAMEADDR(Op, DAG, 3012*0b57cec5SDimitry Andric Subtarget); 3013*0b57cec5SDimitry Andric case ISD::GlobalTLSAddress: return LowerGlobalTLSAddress(Op, DAG); 3014*0b57cec5SDimitry Andric case ISD::GlobalAddress: return LowerGlobalAddress(Op, DAG); 3015*0b57cec5SDimitry Andric case ISD::BlockAddress: return LowerBlockAddress(Op, DAG); 3016*0b57cec5SDimitry Andric case ISD::ConstantPool: return LowerConstantPool(Op, DAG); 3017*0b57cec5SDimitry Andric case ISD::FP_TO_SINT: return LowerFP_TO_SINT(Op, DAG, *this, 3018*0b57cec5SDimitry Andric hasHardQuad); 3019*0b57cec5SDimitry Andric case ISD::SINT_TO_FP: return LowerSINT_TO_FP(Op, DAG, *this, 3020*0b57cec5SDimitry Andric hasHardQuad); 3021*0b57cec5SDimitry Andric case ISD::FP_TO_UINT: return LowerFP_TO_UINT(Op, DAG, *this, 3022*0b57cec5SDimitry Andric hasHardQuad); 3023*0b57cec5SDimitry Andric case ISD::UINT_TO_FP: return LowerUINT_TO_FP(Op, DAG, *this, 3024*0b57cec5SDimitry Andric hasHardQuad); 3025*0b57cec5SDimitry Andric case ISD::BR_CC: return LowerBR_CC(Op, DAG, *this, 3026*0b57cec5SDimitry Andric hasHardQuad); 3027*0b57cec5SDimitry Andric case ISD::SELECT_CC: return LowerSELECT_CC(Op, DAG, *this, 3028*0b57cec5SDimitry Andric hasHardQuad); 3029*0b57cec5SDimitry Andric case ISD::VASTART: return LowerVASTART(Op, DAG, *this); 3030*0b57cec5SDimitry Andric case ISD::VAARG: return LowerVAARG(Op, DAG); 3031*0b57cec5SDimitry Andric case ISD::DYNAMIC_STACKALLOC: return LowerDYNAMIC_STACKALLOC(Op, DAG, 3032*0b57cec5SDimitry Andric Subtarget); 3033*0b57cec5SDimitry Andric 3034*0b57cec5SDimitry Andric case ISD::LOAD: return LowerLOAD(Op, DAG); 3035*0b57cec5SDimitry Andric case ISD::STORE: return LowerSTORE(Op, DAG); 3036*0b57cec5SDimitry Andric case ISD::FADD: return LowerF128Op(Op, DAG, 3037*0b57cec5SDimitry Andric getLibcallName(RTLIB::ADD_F128), 2); 3038*0b57cec5SDimitry Andric case ISD::FSUB: return LowerF128Op(Op, DAG, 3039*0b57cec5SDimitry Andric getLibcallName(RTLIB::SUB_F128), 2); 3040*0b57cec5SDimitry Andric case ISD::FMUL: return LowerF128Op(Op, DAG, 3041*0b57cec5SDimitry Andric getLibcallName(RTLIB::MUL_F128), 2); 3042*0b57cec5SDimitry Andric case ISD::FDIV: return LowerF128Op(Op, DAG, 3043*0b57cec5SDimitry Andric getLibcallName(RTLIB::DIV_F128), 2); 3044*0b57cec5SDimitry Andric case ISD::FSQRT: return LowerF128Op(Op, DAG, 3045*0b57cec5SDimitry Andric getLibcallName(RTLIB::SQRT_F128),1); 3046*0b57cec5SDimitry Andric case ISD::FABS: 3047*0b57cec5SDimitry Andric case ISD::FNEG: return LowerFNEGorFABS(Op, DAG, isV9); 3048*0b57cec5SDimitry Andric case ISD::FP_EXTEND: return LowerF128_FPEXTEND(Op, DAG, *this); 3049*0b57cec5SDimitry Andric case ISD::FP_ROUND: return LowerF128_FPROUND(Op, DAG, *this); 3050*0b57cec5SDimitry Andric case ISD::ADDC: 3051*0b57cec5SDimitry Andric case ISD::ADDE: 3052*0b57cec5SDimitry Andric case ISD::SUBC: 3053*0b57cec5SDimitry Andric case ISD::SUBE: return LowerADDC_ADDE_SUBC_SUBE(Op, DAG); 3054*0b57cec5SDimitry Andric case ISD::UMULO: 3055*0b57cec5SDimitry Andric case ISD::SMULO: return LowerUMULO_SMULO(Op, DAG, *this); 3056*0b57cec5SDimitry Andric case ISD::ATOMIC_LOAD: 3057*0b57cec5SDimitry Andric case ISD::ATOMIC_STORE: return LowerATOMIC_LOAD_STORE(Op, DAG); 3058*0b57cec5SDimitry Andric case ISD::INTRINSIC_WO_CHAIN: return LowerINTRINSIC_WO_CHAIN(Op, DAG); 3059*0b57cec5SDimitry Andric } 3060*0b57cec5SDimitry Andric } 3061*0b57cec5SDimitry Andric 3062*0b57cec5SDimitry Andric SDValue SparcTargetLowering::bitcastConstantFPToInt(ConstantFPSDNode *C, 3063*0b57cec5SDimitry Andric const SDLoc &DL, 3064*0b57cec5SDimitry Andric SelectionDAG &DAG) const { 3065*0b57cec5SDimitry Andric APInt V = C->getValueAPF().bitcastToAPInt(); 3066*0b57cec5SDimitry Andric SDValue Lo = DAG.getConstant(V.zextOrTrunc(32), DL, MVT::i32); 3067*0b57cec5SDimitry Andric SDValue Hi = DAG.getConstant(V.lshr(32).zextOrTrunc(32), DL, MVT::i32); 3068*0b57cec5SDimitry Andric if (DAG.getDataLayout().isLittleEndian()) 3069*0b57cec5SDimitry Andric std::swap(Lo, Hi); 3070*0b57cec5SDimitry Andric return DAG.getBuildVector(MVT::v2i32, DL, {Hi, Lo}); 3071*0b57cec5SDimitry Andric } 3072*0b57cec5SDimitry Andric 3073*0b57cec5SDimitry Andric SDValue SparcTargetLowering::PerformBITCASTCombine(SDNode *N, 3074*0b57cec5SDimitry Andric DAGCombinerInfo &DCI) const { 3075*0b57cec5SDimitry Andric SDLoc dl(N); 3076*0b57cec5SDimitry Andric SDValue Src = N->getOperand(0); 3077*0b57cec5SDimitry Andric 3078*0b57cec5SDimitry Andric if (isa<ConstantFPSDNode>(Src) && N->getSimpleValueType(0) == MVT::v2i32 && 3079*0b57cec5SDimitry Andric Src.getSimpleValueType() == MVT::f64) 3080*0b57cec5SDimitry Andric return bitcastConstantFPToInt(cast<ConstantFPSDNode>(Src), dl, DCI.DAG); 3081*0b57cec5SDimitry Andric 3082*0b57cec5SDimitry Andric return SDValue(); 3083*0b57cec5SDimitry Andric } 3084*0b57cec5SDimitry Andric 3085*0b57cec5SDimitry Andric SDValue SparcTargetLowering::PerformDAGCombine(SDNode *N, 3086*0b57cec5SDimitry Andric DAGCombinerInfo &DCI) const { 3087*0b57cec5SDimitry Andric switch (N->getOpcode()) { 3088*0b57cec5SDimitry Andric default: 3089*0b57cec5SDimitry Andric break; 3090*0b57cec5SDimitry Andric case ISD::BITCAST: 3091*0b57cec5SDimitry Andric return PerformBITCASTCombine(N, DCI); 3092*0b57cec5SDimitry Andric } 3093*0b57cec5SDimitry Andric return SDValue(); 3094*0b57cec5SDimitry Andric } 3095*0b57cec5SDimitry Andric 3096*0b57cec5SDimitry Andric MachineBasicBlock * 3097*0b57cec5SDimitry Andric SparcTargetLowering::EmitInstrWithCustomInserter(MachineInstr &MI, 3098*0b57cec5SDimitry Andric MachineBasicBlock *BB) const { 3099*0b57cec5SDimitry Andric switch (MI.getOpcode()) { 3100*0b57cec5SDimitry Andric default: llvm_unreachable("Unknown SELECT_CC!"); 3101*0b57cec5SDimitry Andric case SP::SELECT_CC_Int_ICC: 3102*0b57cec5SDimitry Andric case SP::SELECT_CC_FP_ICC: 3103*0b57cec5SDimitry Andric case SP::SELECT_CC_DFP_ICC: 3104*0b57cec5SDimitry Andric case SP::SELECT_CC_QFP_ICC: 3105*0b57cec5SDimitry Andric return expandSelectCC(MI, BB, SP::BCOND); 3106*0b57cec5SDimitry Andric case SP::SELECT_CC_Int_FCC: 3107*0b57cec5SDimitry Andric case SP::SELECT_CC_FP_FCC: 3108*0b57cec5SDimitry Andric case SP::SELECT_CC_DFP_FCC: 3109*0b57cec5SDimitry Andric case SP::SELECT_CC_QFP_FCC: 3110*0b57cec5SDimitry Andric return expandSelectCC(MI, BB, SP::FBCOND); 3111*0b57cec5SDimitry Andric } 3112*0b57cec5SDimitry Andric } 3113*0b57cec5SDimitry Andric 3114*0b57cec5SDimitry Andric MachineBasicBlock * 3115*0b57cec5SDimitry Andric SparcTargetLowering::expandSelectCC(MachineInstr &MI, MachineBasicBlock *BB, 3116*0b57cec5SDimitry Andric unsigned BROpcode) const { 3117*0b57cec5SDimitry Andric const TargetInstrInfo &TII = *Subtarget->getInstrInfo(); 3118*0b57cec5SDimitry Andric DebugLoc dl = MI.getDebugLoc(); 3119*0b57cec5SDimitry Andric unsigned CC = (SPCC::CondCodes)MI.getOperand(3).getImm(); 3120*0b57cec5SDimitry Andric 3121*0b57cec5SDimitry Andric // To "insert" a SELECT_CC instruction, we actually have to insert the 3122*0b57cec5SDimitry Andric // triangle control-flow pattern. The incoming instruction knows the 3123*0b57cec5SDimitry Andric // destination vreg to set, the condition code register to branch on, the 3124*0b57cec5SDimitry Andric // true/false values to select between, and the condition code for the branch. 3125*0b57cec5SDimitry Andric // 3126*0b57cec5SDimitry Andric // We produce the following control flow: 3127*0b57cec5SDimitry Andric // ThisMBB 3128*0b57cec5SDimitry Andric // | \ 3129*0b57cec5SDimitry Andric // | IfFalseMBB 3130*0b57cec5SDimitry Andric // | / 3131*0b57cec5SDimitry Andric // SinkMBB 3132*0b57cec5SDimitry Andric const BasicBlock *LLVM_BB = BB->getBasicBlock(); 3133*0b57cec5SDimitry Andric MachineFunction::iterator It = ++BB->getIterator(); 3134*0b57cec5SDimitry Andric 3135*0b57cec5SDimitry Andric MachineBasicBlock *ThisMBB = BB; 3136*0b57cec5SDimitry Andric MachineFunction *F = BB->getParent(); 3137*0b57cec5SDimitry Andric MachineBasicBlock *IfFalseMBB = F->CreateMachineBasicBlock(LLVM_BB); 3138*0b57cec5SDimitry Andric MachineBasicBlock *SinkMBB = F->CreateMachineBasicBlock(LLVM_BB); 3139*0b57cec5SDimitry Andric F->insert(It, IfFalseMBB); 3140*0b57cec5SDimitry Andric F->insert(It, SinkMBB); 3141*0b57cec5SDimitry Andric 3142*0b57cec5SDimitry Andric // Transfer the remainder of ThisMBB and its successor edges to SinkMBB. 3143*0b57cec5SDimitry Andric SinkMBB->splice(SinkMBB->begin(), ThisMBB, 3144*0b57cec5SDimitry Andric std::next(MachineBasicBlock::iterator(MI)), ThisMBB->end()); 3145*0b57cec5SDimitry Andric SinkMBB->transferSuccessorsAndUpdatePHIs(ThisMBB); 3146*0b57cec5SDimitry Andric 3147*0b57cec5SDimitry Andric // Set the new successors for ThisMBB. 3148*0b57cec5SDimitry Andric ThisMBB->addSuccessor(IfFalseMBB); 3149*0b57cec5SDimitry Andric ThisMBB->addSuccessor(SinkMBB); 3150*0b57cec5SDimitry Andric 3151*0b57cec5SDimitry Andric BuildMI(ThisMBB, dl, TII.get(BROpcode)) 3152*0b57cec5SDimitry Andric .addMBB(SinkMBB) 3153*0b57cec5SDimitry Andric .addImm(CC); 3154*0b57cec5SDimitry Andric 3155*0b57cec5SDimitry Andric // IfFalseMBB just falls through to SinkMBB. 3156*0b57cec5SDimitry Andric IfFalseMBB->addSuccessor(SinkMBB); 3157*0b57cec5SDimitry Andric 3158*0b57cec5SDimitry Andric // %Result = phi [ %TrueValue, ThisMBB ], [ %FalseValue, IfFalseMBB ] 3159*0b57cec5SDimitry Andric BuildMI(*SinkMBB, SinkMBB->begin(), dl, TII.get(SP::PHI), 3160*0b57cec5SDimitry Andric MI.getOperand(0).getReg()) 3161*0b57cec5SDimitry Andric .addReg(MI.getOperand(1).getReg()) 3162*0b57cec5SDimitry Andric .addMBB(ThisMBB) 3163*0b57cec5SDimitry Andric .addReg(MI.getOperand(2).getReg()) 3164*0b57cec5SDimitry Andric .addMBB(IfFalseMBB); 3165*0b57cec5SDimitry Andric 3166*0b57cec5SDimitry Andric MI.eraseFromParent(); // The pseudo instruction is gone now. 3167*0b57cec5SDimitry Andric return SinkMBB; 3168*0b57cec5SDimitry Andric } 3169*0b57cec5SDimitry Andric 3170*0b57cec5SDimitry Andric //===----------------------------------------------------------------------===// 3171*0b57cec5SDimitry Andric // Sparc Inline Assembly Support 3172*0b57cec5SDimitry Andric //===----------------------------------------------------------------------===// 3173*0b57cec5SDimitry Andric 3174*0b57cec5SDimitry Andric /// getConstraintType - Given a constraint letter, return the type of 3175*0b57cec5SDimitry Andric /// constraint it is for this target. 3176*0b57cec5SDimitry Andric SparcTargetLowering::ConstraintType 3177*0b57cec5SDimitry Andric SparcTargetLowering::getConstraintType(StringRef Constraint) const { 3178*0b57cec5SDimitry Andric if (Constraint.size() == 1) { 3179*0b57cec5SDimitry Andric switch (Constraint[0]) { 3180*0b57cec5SDimitry Andric default: break; 3181*0b57cec5SDimitry Andric case 'r': 3182*0b57cec5SDimitry Andric case 'f': 3183*0b57cec5SDimitry Andric case 'e': 3184*0b57cec5SDimitry Andric return C_RegisterClass; 3185*0b57cec5SDimitry Andric case 'I': // SIMM13 3186*0b57cec5SDimitry Andric return C_Immediate; 3187*0b57cec5SDimitry Andric } 3188*0b57cec5SDimitry Andric } 3189*0b57cec5SDimitry Andric 3190*0b57cec5SDimitry Andric return TargetLowering::getConstraintType(Constraint); 3191*0b57cec5SDimitry Andric } 3192*0b57cec5SDimitry Andric 3193*0b57cec5SDimitry Andric TargetLowering::ConstraintWeight SparcTargetLowering:: 3194*0b57cec5SDimitry Andric getSingleConstraintMatchWeight(AsmOperandInfo &info, 3195*0b57cec5SDimitry Andric const char *constraint) const { 3196*0b57cec5SDimitry Andric ConstraintWeight weight = CW_Invalid; 3197*0b57cec5SDimitry Andric Value *CallOperandVal = info.CallOperandVal; 3198*0b57cec5SDimitry Andric // If we don't have a value, we can't do a match, 3199*0b57cec5SDimitry Andric // but allow it at the lowest weight. 3200*0b57cec5SDimitry Andric if (!CallOperandVal) 3201*0b57cec5SDimitry Andric return CW_Default; 3202*0b57cec5SDimitry Andric 3203*0b57cec5SDimitry Andric // Look at the constraint type. 3204*0b57cec5SDimitry Andric switch (*constraint) { 3205*0b57cec5SDimitry Andric default: 3206*0b57cec5SDimitry Andric weight = TargetLowering::getSingleConstraintMatchWeight(info, constraint); 3207*0b57cec5SDimitry Andric break; 3208*0b57cec5SDimitry Andric case 'I': // SIMM13 3209*0b57cec5SDimitry Andric if (ConstantInt *C = dyn_cast<ConstantInt>(info.CallOperandVal)) { 3210*0b57cec5SDimitry Andric if (isInt<13>(C->getSExtValue())) 3211*0b57cec5SDimitry Andric weight = CW_Constant; 3212*0b57cec5SDimitry Andric } 3213*0b57cec5SDimitry Andric break; 3214*0b57cec5SDimitry Andric } 3215*0b57cec5SDimitry Andric return weight; 3216*0b57cec5SDimitry Andric } 3217*0b57cec5SDimitry Andric 3218*0b57cec5SDimitry Andric /// LowerAsmOperandForConstraint - Lower the specified operand into the Ops 3219*0b57cec5SDimitry Andric /// vector. If it is invalid, don't add anything to Ops. 3220*0b57cec5SDimitry Andric void SparcTargetLowering:: 3221*0b57cec5SDimitry Andric LowerAsmOperandForConstraint(SDValue Op, 3222*0b57cec5SDimitry Andric std::string &Constraint, 3223*0b57cec5SDimitry Andric std::vector<SDValue> &Ops, 3224*0b57cec5SDimitry Andric SelectionDAG &DAG) const { 3225*0b57cec5SDimitry Andric SDValue Result(nullptr, 0); 3226*0b57cec5SDimitry Andric 3227*0b57cec5SDimitry Andric // Only support length 1 constraints for now. 3228*0b57cec5SDimitry Andric if (Constraint.length() > 1) 3229*0b57cec5SDimitry Andric return; 3230*0b57cec5SDimitry Andric 3231*0b57cec5SDimitry Andric char ConstraintLetter = Constraint[0]; 3232*0b57cec5SDimitry Andric switch (ConstraintLetter) { 3233*0b57cec5SDimitry Andric default: break; 3234*0b57cec5SDimitry Andric case 'I': 3235*0b57cec5SDimitry Andric if (ConstantSDNode *C = dyn_cast<ConstantSDNode>(Op)) { 3236*0b57cec5SDimitry Andric if (isInt<13>(C->getSExtValue())) { 3237*0b57cec5SDimitry Andric Result = DAG.getTargetConstant(C->getSExtValue(), SDLoc(Op), 3238*0b57cec5SDimitry Andric Op.getValueType()); 3239*0b57cec5SDimitry Andric break; 3240*0b57cec5SDimitry Andric } 3241*0b57cec5SDimitry Andric return; 3242*0b57cec5SDimitry Andric } 3243*0b57cec5SDimitry Andric } 3244*0b57cec5SDimitry Andric 3245*0b57cec5SDimitry Andric if (Result.getNode()) { 3246*0b57cec5SDimitry Andric Ops.push_back(Result); 3247*0b57cec5SDimitry Andric return; 3248*0b57cec5SDimitry Andric } 3249*0b57cec5SDimitry Andric TargetLowering::LowerAsmOperandForConstraint(Op, Constraint, Ops, DAG); 3250*0b57cec5SDimitry Andric } 3251*0b57cec5SDimitry Andric 3252*0b57cec5SDimitry Andric std::pair<unsigned, const TargetRegisterClass *> 3253*0b57cec5SDimitry Andric SparcTargetLowering::getRegForInlineAsmConstraint(const TargetRegisterInfo *TRI, 3254*0b57cec5SDimitry Andric StringRef Constraint, 3255*0b57cec5SDimitry Andric MVT VT) const { 3256*0b57cec5SDimitry Andric if (Constraint.size() == 1) { 3257*0b57cec5SDimitry Andric switch (Constraint[0]) { 3258*0b57cec5SDimitry Andric case 'r': 3259*0b57cec5SDimitry Andric if (VT == MVT::v2i32) 3260*0b57cec5SDimitry Andric return std::make_pair(0U, &SP::IntPairRegClass); 3261*0b57cec5SDimitry Andric else if (Subtarget->is64Bit()) 3262*0b57cec5SDimitry Andric return std::make_pair(0U, &SP::I64RegsRegClass); 3263*0b57cec5SDimitry Andric else 3264*0b57cec5SDimitry Andric return std::make_pair(0U, &SP::IntRegsRegClass); 3265*0b57cec5SDimitry Andric case 'f': 3266*0b57cec5SDimitry Andric if (VT == MVT::f32 || VT == MVT::i32) 3267*0b57cec5SDimitry Andric return std::make_pair(0U, &SP::FPRegsRegClass); 3268*0b57cec5SDimitry Andric else if (VT == MVT::f64 || VT == MVT::i64) 3269*0b57cec5SDimitry Andric return std::make_pair(0U, &SP::LowDFPRegsRegClass); 3270*0b57cec5SDimitry Andric else if (VT == MVT::f128) 3271*0b57cec5SDimitry Andric return std::make_pair(0U, &SP::LowQFPRegsRegClass); 3272*0b57cec5SDimitry Andric // This will generate an error message 3273*0b57cec5SDimitry Andric return std::make_pair(0U, nullptr); 3274*0b57cec5SDimitry Andric case 'e': 3275*0b57cec5SDimitry Andric if (VT == MVT::f32 || VT == MVT::i32) 3276*0b57cec5SDimitry Andric return std::make_pair(0U, &SP::FPRegsRegClass); 3277*0b57cec5SDimitry Andric else if (VT == MVT::f64 || VT == MVT::i64 ) 3278*0b57cec5SDimitry Andric return std::make_pair(0U, &SP::DFPRegsRegClass); 3279*0b57cec5SDimitry Andric else if (VT == MVT::f128) 3280*0b57cec5SDimitry Andric return std::make_pair(0U, &SP::QFPRegsRegClass); 3281*0b57cec5SDimitry Andric // This will generate an error message 3282*0b57cec5SDimitry Andric return std::make_pair(0U, nullptr); 3283*0b57cec5SDimitry Andric } 3284*0b57cec5SDimitry Andric } else if (!Constraint.empty() && Constraint.size() <= 5 3285*0b57cec5SDimitry Andric && Constraint[0] == '{' && *(Constraint.end()-1) == '}') { 3286*0b57cec5SDimitry Andric // constraint = '{r<d>}' 3287*0b57cec5SDimitry Andric // Remove the braces from around the name. 3288*0b57cec5SDimitry Andric StringRef name(Constraint.data()+1, Constraint.size()-2); 3289*0b57cec5SDimitry Andric // Handle register aliases: 3290*0b57cec5SDimitry Andric // r0-r7 -> g0-g7 3291*0b57cec5SDimitry Andric // r8-r15 -> o0-o7 3292*0b57cec5SDimitry Andric // r16-r23 -> l0-l7 3293*0b57cec5SDimitry Andric // r24-r31 -> i0-i7 3294*0b57cec5SDimitry Andric uint64_t intVal = 0; 3295*0b57cec5SDimitry Andric if (name.substr(0, 1).equals("r") 3296*0b57cec5SDimitry Andric && !name.substr(1).getAsInteger(10, intVal) && intVal <= 31) { 3297*0b57cec5SDimitry Andric const char regTypes[] = { 'g', 'o', 'l', 'i' }; 3298*0b57cec5SDimitry Andric char regType = regTypes[intVal/8]; 3299*0b57cec5SDimitry Andric char regIdx = '0' + (intVal % 8); 3300*0b57cec5SDimitry Andric char tmp[] = { '{', regType, regIdx, '}', 0 }; 3301*0b57cec5SDimitry Andric std::string newConstraint = std::string(tmp); 3302*0b57cec5SDimitry Andric return TargetLowering::getRegForInlineAsmConstraint(TRI, newConstraint, 3303*0b57cec5SDimitry Andric VT); 3304*0b57cec5SDimitry Andric } 3305*0b57cec5SDimitry Andric if (name.substr(0, 1).equals("f") && 3306*0b57cec5SDimitry Andric !name.substr(1).getAsInteger(10, intVal) && intVal <= 63) { 3307*0b57cec5SDimitry Andric std::string newConstraint; 3308*0b57cec5SDimitry Andric 3309*0b57cec5SDimitry Andric if (VT == MVT::f32 || VT == MVT::Other) { 3310*0b57cec5SDimitry Andric newConstraint = "{f" + utostr(intVal) + "}"; 3311*0b57cec5SDimitry Andric } else if (VT == MVT::f64 && (intVal % 2 == 0)) { 3312*0b57cec5SDimitry Andric newConstraint = "{d" + utostr(intVal / 2) + "}"; 3313*0b57cec5SDimitry Andric } else if (VT == MVT::f128 && (intVal % 4 == 0)) { 3314*0b57cec5SDimitry Andric newConstraint = "{q" + utostr(intVal / 4) + "}"; 3315*0b57cec5SDimitry Andric } else { 3316*0b57cec5SDimitry Andric return std::make_pair(0U, nullptr); 3317*0b57cec5SDimitry Andric } 3318*0b57cec5SDimitry Andric return TargetLowering::getRegForInlineAsmConstraint(TRI, newConstraint, 3319*0b57cec5SDimitry Andric VT); 3320*0b57cec5SDimitry Andric } 3321*0b57cec5SDimitry Andric } 3322*0b57cec5SDimitry Andric 3323*0b57cec5SDimitry Andric return TargetLowering::getRegForInlineAsmConstraint(TRI, Constraint, VT); 3324*0b57cec5SDimitry Andric } 3325*0b57cec5SDimitry Andric 3326*0b57cec5SDimitry Andric bool 3327*0b57cec5SDimitry Andric SparcTargetLowering::isOffsetFoldingLegal(const GlobalAddressSDNode *GA) const { 3328*0b57cec5SDimitry Andric // The Sparc target isn't yet aware of offsets. 3329*0b57cec5SDimitry Andric return false; 3330*0b57cec5SDimitry Andric } 3331*0b57cec5SDimitry Andric 3332*0b57cec5SDimitry Andric void SparcTargetLowering::ReplaceNodeResults(SDNode *N, 3333*0b57cec5SDimitry Andric SmallVectorImpl<SDValue>& Results, 3334*0b57cec5SDimitry Andric SelectionDAG &DAG) const { 3335*0b57cec5SDimitry Andric 3336*0b57cec5SDimitry Andric SDLoc dl(N); 3337*0b57cec5SDimitry Andric 3338*0b57cec5SDimitry Andric RTLIB::Libcall libCall = RTLIB::UNKNOWN_LIBCALL; 3339*0b57cec5SDimitry Andric 3340*0b57cec5SDimitry Andric switch (N->getOpcode()) { 3341*0b57cec5SDimitry Andric default: 3342*0b57cec5SDimitry Andric llvm_unreachable("Do not know how to custom type legalize this operation!"); 3343*0b57cec5SDimitry Andric 3344*0b57cec5SDimitry Andric case ISD::FP_TO_SINT: 3345*0b57cec5SDimitry Andric case ISD::FP_TO_UINT: 3346*0b57cec5SDimitry Andric // Custom lower only if it involves f128 or i64. 3347*0b57cec5SDimitry Andric if (N->getOperand(0).getValueType() != MVT::f128 3348*0b57cec5SDimitry Andric || N->getValueType(0) != MVT::i64) 3349*0b57cec5SDimitry Andric return; 3350*0b57cec5SDimitry Andric libCall = ((N->getOpcode() == ISD::FP_TO_SINT) 3351*0b57cec5SDimitry Andric ? RTLIB::FPTOSINT_F128_I64 3352*0b57cec5SDimitry Andric : RTLIB::FPTOUINT_F128_I64); 3353*0b57cec5SDimitry Andric 3354*0b57cec5SDimitry Andric Results.push_back(LowerF128Op(SDValue(N, 0), 3355*0b57cec5SDimitry Andric DAG, 3356*0b57cec5SDimitry Andric getLibcallName(libCall), 3357*0b57cec5SDimitry Andric 1)); 3358*0b57cec5SDimitry Andric return; 3359*0b57cec5SDimitry Andric case ISD::READCYCLECOUNTER: { 3360*0b57cec5SDimitry Andric assert(Subtarget->hasLeonCycleCounter()); 3361*0b57cec5SDimitry Andric SDValue Lo = DAG.getCopyFromReg(N->getOperand(0), dl, SP::ASR23, MVT::i32); 3362*0b57cec5SDimitry Andric SDValue Hi = DAG.getCopyFromReg(Lo, dl, SP::G0, MVT::i32); 3363*0b57cec5SDimitry Andric SDValue Ops[] = { Lo, Hi }; 3364*0b57cec5SDimitry Andric SDValue Pair = DAG.getNode(ISD::BUILD_PAIR, dl, MVT::i64, Ops); 3365*0b57cec5SDimitry Andric Results.push_back(Pair); 3366*0b57cec5SDimitry Andric Results.push_back(N->getOperand(0)); 3367*0b57cec5SDimitry Andric return; 3368*0b57cec5SDimitry Andric } 3369*0b57cec5SDimitry Andric case ISD::SINT_TO_FP: 3370*0b57cec5SDimitry Andric case ISD::UINT_TO_FP: 3371*0b57cec5SDimitry Andric // Custom lower only if it involves f128 or i64. 3372*0b57cec5SDimitry Andric if (N->getValueType(0) != MVT::f128 3373*0b57cec5SDimitry Andric || N->getOperand(0).getValueType() != MVT::i64) 3374*0b57cec5SDimitry Andric return; 3375*0b57cec5SDimitry Andric 3376*0b57cec5SDimitry Andric libCall = ((N->getOpcode() == ISD::SINT_TO_FP) 3377*0b57cec5SDimitry Andric ? RTLIB::SINTTOFP_I64_F128 3378*0b57cec5SDimitry Andric : RTLIB::UINTTOFP_I64_F128); 3379*0b57cec5SDimitry Andric 3380*0b57cec5SDimitry Andric Results.push_back(LowerF128Op(SDValue(N, 0), 3381*0b57cec5SDimitry Andric DAG, 3382*0b57cec5SDimitry Andric getLibcallName(libCall), 3383*0b57cec5SDimitry Andric 1)); 3384*0b57cec5SDimitry Andric return; 3385*0b57cec5SDimitry Andric case ISD::LOAD: { 3386*0b57cec5SDimitry Andric LoadSDNode *Ld = cast<LoadSDNode>(N); 3387*0b57cec5SDimitry Andric // Custom handling only for i64: turn i64 load into a v2i32 load, 3388*0b57cec5SDimitry Andric // and a bitcast. 3389*0b57cec5SDimitry Andric if (Ld->getValueType(0) != MVT::i64 || Ld->getMemoryVT() != MVT::i64) 3390*0b57cec5SDimitry Andric return; 3391*0b57cec5SDimitry Andric 3392*0b57cec5SDimitry Andric SDLoc dl(N); 3393*0b57cec5SDimitry Andric SDValue LoadRes = DAG.getExtLoad( 3394*0b57cec5SDimitry Andric Ld->getExtensionType(), dl, MVT::v2i32, Ld->getChain(), 3395*0b57cec5SDimitry Andric Ld->getBasePtr(), Ld->getPointerInfo(), MVT::v2i32, Ld->getAlignment(), 3396*0b57cec5SDimitry Andric Ld->getMemOperand()->getFlags(), Ld->getAAInfo()); 3397*0b57cec5SDimitry Andric 3398*0b57cec5SDimitry Andric SDValue Res = DAG.getNode(ISD::BITCAST, dl, MVT::i64, LoadRes); 3399*0b57cec5SDimitry Andric Results.push_back(Res); 3400*0b57cec5SDimitry Andric Results.push_back(LoadRes.getValue(1)); 3401*0b57cec5SDimitry Andric return; 3402*0b57cec5SDimitry Andric } 3403*0b57cec5SDimitry Andric } 3404*0b57cec5SDimitry Andric } 3405*0b57cec5SDimitry Andric 3406*0b57cec5SDimitry Andric // Override to enable LOAD_STACK_GUARD lowering on Linux. 3407*0b57cec5SDimitry Andric bool SparcTargetLowering::useLoadStackGuardNode() const { 3408*0b57cec5SDimitry Andric if (!Subtarget->isTargetLinux()) 3409*0b57cec5SDimitry Andric return TargetLowering::useLoadStackGuardNode(); 3410*0b57cec5SDimitry Andric return true; 3411*0b57cec5SDimitry Andric } 3412*0b57cec5SDimitry Andric 3413*0b57cec5SDimitry Andric // Override to disable global variable loading on Linux. 3414*0b57cec5SDimitry Andric void SparcTargetLowering::insertSSPDeclarations(Module &M) const { 3415*0b57cec5SDimitry Andric if (!Subtarget->isTargetLinux()) 3416*0b57cec5SDimitry Andric return TargetLowering::insertSSPDeclarations(M); 3417*0b57cec5SDimitry Andric } 3418