1349cc55cSDimitry Andric //===-- CSKYISelLowering.cpp - CSKY DAG Lowering Implementation ----------===// 2349cc55cSDimitry Andric // 3349cc55cSDimitry Andric // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 4349cc55cSDimitry Andric // See https://llvm.org/LICENSE.txt for license information. 5349cc55cSDimitry Andric // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 6349cc55cSDimitry Andric // 7349cc55cSDimitry Andric //===----------------------------------------------------------------------===// 8349cc55cSDimitry Andric // 9349cc55cSDimitry Andric // This file defines the interfaces that CSKY uses to lower LLVM code into a 10349cc55cSDimitry Andric // selection DAG. 11349cc55cSDimitry Andric // 12349cc55cSDimitry Andric //===----------------------------------------------------------------------===// 13349cc55cSDimitry Andric 14349cc55cSDimitry Andric #include "CSKYISelLowering.h" 15349cc55cSDimitry Andric #include "CSKYCallingConv.h" 1604eeddc0SDimitry Andric #include "CSKYConstantPoolValue.h" 17349cc55cSDimitry Andric #include "CSKYMachineFunctionInfo.h" 18349cc55cSDimitry Andric #include "CSKYRegisterInfo.h" 19349cc55cSDimitry Andric #include "CSKYSubtarget.h" 20349cc55cSDimitry Andric #include "llvm/ADT/Statistic.h" 21349cc55cSDimitry Andric #include "llvm/CodeGen/CallingConvLower.h" 22*81ad6265SDimitry Andric #include "llvm/CodeGen/MachineFrameInfo.h" 23349cc55cSDimitry Andric #include "llvm/CodeGen/MachineJumpTableInfo.h" 24349cc55cSDimitry Andric #include "llvm/Support/Debug.h" 25349cc55cSDimitry Andric 26349cc55cSDimitry Andric using namespace llvm; 27349cc55cSDimitry Andric 28349cc55cSDimitry Andric #define DEBUG_TYPE "csky-isel-lowering" 29349cc55cSDimitry Andric 30349cc55cSDimitry Andric STATISTIC(NumTailCalls, "Number of tail calls"); 31349cc55cSDimitry Andric 32349cc55cSDimitry Andric #include "CSKYGenCallingConv.inc" 33349cc55cSDimitry Andric 34349cc55cSDimitry Andric static const MCPhysReg GPRArgRegs[] = {CSKY::R0, CSKY::R1, CSKY::R2, CSKY::R3}; 35349cc55cSDimitry Andric 36349cc55cSDimitry Andric CSKYTargetLowering::CSKYTargetLowering(const TargetMachine &TM, 37349cc55cSDimitry Andric const CSKYSubtarget &STI) 38349cc55cSDimitry Andric : TargetLowering(TM), Subtarget(STI) { 39349cc55cSDimitry Andric // Register Class 40349cc55cSDimitry Andric addRegisterClass(MVT::i32, &CSKY::GPRRegClass); 41349cc55cSDimitry Andric 4204eeddc0SDimitry Andric if (STI.useHardFloat()) { 4304eeddc0SDimitry Andric if (STI.hasFPUv2SingleFloat()) 4404eeddc0SDimitry Andric addRegisterClass(MVT::f32, &CSKY::sFPR32RegClass); 4504eeddc0SDimitry Andric else if (STI.hasFPUv3SingleFloat()) 4604eeddc0SDimitry Andric addRegisterClass(MVT::f32, &CSKY::FPR32RegClass); 4704eeddc0SDimitry Andric 4804eeddc0SDimitry Andric if (STI.hasFPUv2DoubleFloat()) 4904eeddc0SDimitry Andric addRegisterClass(MVT::f64, &CSKY::sFPR64RegClass); 5004eeddc0SDimitry Andric else if (STI.hasFPUv3DoubleFloat()) 5104eeddc0SDimitry Andric addRegisterClass(MVT::f64, &CSKY::FPR64RegClass); 5204eeddc0SDimitry Andric } 5304eeddc0SDimitry Andric 540eae32dcSDimitry Andric setOperationAction(ISD::ADDCARRY, MVT::i32, Legal); 550eae32dcSDimitry Andric setOperationAction(ISD::SUBCARRY, MVT::i32, Legal); 560eae32dcSDimitry Andric setOperationAction(ISD::BITREVERSE, MVT::i32, Legal); 570eae32dcSDimitry Andric 580eae32dcSDimitry Andric setOperationAction(ISD::SREM, MVT::i32, Expand); 590eae32dcSDimitry Andric setOperationAction(ISD::UREM, MVT::i32, Expand); 600eae32dcSDimitry Andric setOperationAction(ISD::UDIVREM, MVT::i32, Expand); 610eae32dcSDimitry Andric setOperationAction(ISD::SDIVREM, MVT::i32, Expand); 620eae32dcSDimitry Andric setOperationAction(ISD::CTTZ, MVT::i32, Expand); 630eae32dcSDimitry Andric setOperationAction(ISD::CTPOP, MVT::i32, Expand); 640eae32dcSDimitry Andric setOperationAction(ISD::ROTR, MVT::i32, Expand); 650eae32dcSDimitry Andric setOperationAction(ISD::SHL_PARTS, MVT::i32, Expand); 660eae32dcSDimitry Andric setOperationAction(ISD::SRL_PARTS, MVT::i32, Expand); 670eae32dcSDimitry Andric setOperationAction(ISD::SRA_PARTS, MVT::i32, Expand); 680eae32dcSDimitry Andric setOperationAction(ISD::UMUL_LOHI, MVT::i32, Expand); 690eae32dcSDimitry Andric setOperationAction(ISD::SMUL_LOHI, MVT::i32, Expand); 7004eeddc0SDimitry Andric setOperationAction(ISD::SELECT_CC, MVT::i32, Expand); 7104eeddc0SDimitry Andric setOperationAction(ISD::BR_CC, MVT::i32, Expand); 7204eeddc0SDimitry Andric setOperationAction(ISD::BR_JT, MVT::Other, Expand); 730eae32dcSDimitry Andric setOperationAction(ISD::DYNAMIC_STACKALLOC, MVT::i32, Expand); 740eae32dcSDimitry Andric setOperationAction(ISD::STACKSAVE, MVT::Other, Expand); 750eae32dcSDimitry Andric setOperationAction(ISD::STACKRESTORE, MVT::Other, Expand); 760eae32dcSDimitry Andric setOperationAction(ISD::MULHS, MVT::i32, Expand); 770eae32dcSDimitry Andric setOperationAction(ISD::MULHU, MVT::i32, Expand); 7804eeddc0SDimitry Andric setOperationAction(ISD::VAARG, MVT::Other, Expand); 7904eeddc0SDimitry Andric setOperationAction(ISD::VACOPY, MVT::Other, Expand); 8004eeddc0SDimitry Andric setOperationAction(ISD::VAEND, MVT::Other, Expand); 810eae32dcSDimitry Andric 820eae32dcSDimitry Andric setLoadExtAction(ISD::EXTLOAD, MVT::i32, MVT::i1, Promote); 830eae32dcSDimitry Andric setLoadExtAction(ISD::SEXTLOAD, MVT::i32, MVT::i1, Promote); 840eae32dcSDimitry Andric setLoadExtAction(ISD::ZEXTLOAD, MVT::i32, MVT::i1, Promote); 850eae32dcSDimitry Andric 8604eeddc0SDimitry Andric setOperationAction(ISD::GlobalAddress, MVT::i32, Custom); 8704eeddc0SDimitry Andric setOperationAction(ISD::ExternalSymbol, MVT::i32, Custom); 8804eeddc0SDimitry Andric setOperationAction(ISD::GlobalTLSAddress, MVT::i32, Custom); 8904eeddc0SDimitry Andric setOperationAction(ISD::BlockAddress, MVT::i32, Custom); 9004eeddc0SDimitry Andric setOperationAction(ISD::JumpTable, MVT::i32, Custom); 9104eeddc0SDimitry Andric setOperationAction(ISD::VASTART, MVT::Other, Custom); 9204eeddc0SDimitry Andric 930eae32dcSDimitry Andric if (!Subtarget.hasE2()) { 940eae32dcSDimitry Andric setLoadExtAction(ISD::SEXTLOAD, MVT::i32, MVT::i8, Expand); 950eae32dcSDimitry Andric setLoadExtAction(ISD::SEXTLOAD, MVT::i32, MVT::i16, Expand); 960eae32dcSDimitry Andric setOperationAction(ISD::CTLZ, MVT::i32, Expand); 970eae32dcSDimitry Andric setOperationAction(ISD::BSWAP, MVT::i32, Expand); 980eae32dcSDimitry Andric } 990eae32dcSDimitry Andric 1000eae32dcSDimitry Andric if (!Subtarget.has2E3()) { 1010eae32dcSDimitry Andric setOperationAction(ISD::ABS, MVT::i32, Expand); 1020eae32dcSDimitry Andric setOperationAction(ISD::BITREVERSE, MVT::i32, Expand); 1030eae32dcSDimitry Andric setOperationAction(ISD::SDIV, MVT::i32, Expand); 1040eae32dcSDimitry Andric setOperationAction(ISD::UDIV, MVT::i32, Expand); 1050eae32dcSDimitry Andric } 1060eae32dcSDimitry Andric 10704eeddc0SDimitry Andric setOperationAction(ISD::ATOMIC_FENCE, MVT::Other, Expand); 10804eeddc0SDimitry Andric 10904eeddc0SDimitry Andric // Float 11004eeddc0SDimitry Andric 11104eeddc0SDimitry Andric ISD::CondCode FPCCToExtend[] = { 11204eeddc0SDimitry Andric ISD::SETONE, ISD::SETUEQ, ISD::SETUGT, 11304eeddc0SDimitry Andric ISD::SETUGE, ISD::SETULT, ISD::SETULE, 11404eeddc0SDimitry Andric }; 11504eeddc0SDimitry Andric 11604eeddc0SDimitry Andric ISD::NodeType FPOpToExpand[] = {ISD::FSIN, ISD::FCOS, ISD::FSINCOS, 11704eeddc0SDimitry Andric ISD::FPOW, ISD::FREM, ISD::FCOPYSIGN}; 11804eeddc0SDimitry Andric 11904eeddc0SDimitry Andric if (STI.useHardFloat()) { 12004eeddc0SDimitry Andric 12104eeddc0SDimitry Andric MVT AllVTy[] = {MVT::f32, MVT::f64}; 12204eeddc0SDimitry Andric 12304eeddc0SDimitry Andric for (auto VT : AllVTy) { 12404eeddc0SDimitry Andric setOperationAction(ISD::FREM, VT, Expand); 12504eeddc0SDimitry Andric setOperationAction(ISD::SELECT_CC, VT, Expand); 12604eeddc0SDimitry Andric setOperationAction(ISD::BR_CC, VT, Expand); 12704eeddc0SDimitry Andric 12804eeddc0SDimitry Andric for (auto CC : FPCCToExtend) 12904eeddc0SDimitry Andric setCondCodeAction(CC, VT, Expand); 13004eeddc0SDimitry Andric for (auto Op : FPOpToExpand) 13104eeddc0SDimitry Andric setOperationAction(Op, VT, Expand); 13204eeddc0SDimitry Andric } 13304eeddc0SDimitry Andric 13404eeddc0SDimitry Andric if (STI.hasFPUv2SingleFloat() || STI.hasFPUv3SingleFloat()) { 13504eeddc0SDimitry Andric setOperationAction(ISD::ConstantFP, MVT::f32, Legal); 13604eeddc0SDimitry Andric } 13704eeddc0SDimitry Andric if (STI.hasFPUv2DoubleFloat() || STI.hasFPUv3DoubleFloat()) { 13804eeddc0SDimitry Andric setLoadExtAction(ISD::EXTLOAD, MVT::f64, MVT::f32, Expand); 13904eeddc0SDimitry Andric setTruncStoreAction(MVT::f64, MVT::f32, Expand); 14004eeddc0SDimitry Andric } 14104eeddc0SDimitry Andric } 14204eeddc0SDimitry Andric 143349cc55cSDimitry Andric // Compute derived properties from the register classes. 144349cc55cSDimitry Andric computeRegisterProperties(STI.getRegisterInfo()); 145349cc55cSDimitry Andric 146349cc55cSDimitry Andric setBooleanContents(UndefinedBooleanContent); 147349cc55cSDimitry Andric setBooleanVectorContents(ZeroOrNegativeOneBooleanContent); 148349cc55cSDimitry Andric 149349cc55cSDimitry Andric // TODO: Add atomic support fully. 150349cc55cSDimitry Andric setMaxAtomicSizeInBitsSupported(0); 151349cc55cSDimitry Andric 152349cc55cSDimitry Andric setStackPointerRegisterToSaveRestore(CSKY::R14); 153349cc55cSDimitry Andric const Align FunctionAlignment(2); 154349cc55cSDimitry Andric setMinFunctionAlignment(FunctionAlignment); 155349cc55cSDimitry Andric setSchedulingPreference(Sched::Source); 156349cc55cSDimitry Andric } 157349cc55cSDimitry Andric 15804eeddc0SDimitry Andric SDValue CSKYTargetLowering::LowerOperation(SDValue Op, 15904eeddc0SDimitry Andric SelectionDAG &DAG) const { 16004eeddc0SDimitry Andric switch (Op.getOpcode()) { 16104eeddc0SDimitry Andric default: 16204eeddc0SDimitry Andric llvm_unreachable("unimplemented op"); 16304eeddc0SDimitry Andric case ISD::GlobalAddress: 16404eeddc0SDimitry Andric return LowerGlobalAddress(Op, DAG); 16504eeddc0SDimitry Andric case ISD::ExternalSymbol: 16604eeddc0SDimitry Andric return LowerExternalSymbol(Op, DAG); 16704eeddc0SDimitry Andric case ISD::GlobalTLSAddress: 16804eeddc0SDimitry Andric return LowerGlobalTLSAddress(Op, DAG); 16904eeddc0SDimitry Andric case ISD::JumpTable: 17004eeddc0SDimitry Andric return LowerJumpTable(Op, DAG); 17104eeddc0SDimitry Andric case ISD::BlockAddress: 17204eeddc0SDimitry Andric return LowerBlockAddress(Op, DAG); 17304eeddc0SDimitry Andric case ISD::VASTART: 17404eeddc0SDimitry Andric return LowerVASTART(Op, DAG); 17504eeddc0SDimitry Andric case ISD::FRAMEADDR: 17604eeddc0SDimitry Andric return LowerFRAMEADDR(Op, DAG); 17704eeddc0SDimitry Andric case ISD::RETURNADDR: 17804eeddc0SDimitry Andric return LowerRETURNADDR(Op, DAG); 17904eeddc0SDimitry Andric } 18004eeddc0SDimitry Andric } 18104eeddc0SDimitry Andric 182349cc55cSDimitry Andric EVT CSKYTargetLowering::getSetCCResultType(const DataLayout &DL, 183349cc55cSDimitry Andric LLVMContext &Context, EVT VT) const { 184349cc55cSDimitry Andric if (!VT.isVector()) 185349cc55cSDimitry Andric return MVT::i32; 186349cc55cSDimitry Andric 187349cc55cSDimitry Andric return VT.changeVectorElementTypeToInteger(); 188349cc55cSDimitry Andric } 189349cc55cSDimitry Andric 190349cc55cSDimitry Andric static SDValue convertValVTToLocVT(SelectionDAG &DAG, SDValue Val, 191349cc55cSDimitry Andric const CCValAssign &VA, const SDLoc &DL) { 192349cc55cSDimitry Andric EVT LocVT = VA.getLocVT(); 193349cc55cSDimitry Andric 194349cc55cSDimitry Andric switch (VA.getLocInfo()) { 195349cc55cSDimitry Andric default: 196349cc55cSDimitry Andric llvm_unreachable("Unexpected CCValAssign::LocInfo"); 197349cc55cSDimitry Andric case CCValAssign::Full: 198349cc55cSDimitry Andric break; 199349cc55cSDimitry Andric case CCValAssign::BCvt: 200349cc55cSDimitry Andric Val = DAG.getNode(ISD::BITCAST, DL, LocVT, Val); 201349cc55cSDimitry Andric break; 202349cc55cSDimitry Andric } 203349cc55cSDimitry Andric return Val; 204349cc55cSDimitry Andric } 205349cc55cSDimitry Andric 206349cc55cSDimitry Andric static SDValue convertLocVTToValVT(SelectionDAG &DAG, SDValue Val, 207349cc55cSDimitry Andric const CCValAssign &VA, const SDLoc &DL) { 208349cc55cSDimitry Andric switch (VA.getLocInfo()) { 209349cc55cSDimitry Andric default: 210349cc55cSDimitry Andric llvm_unreachable("Unexpected CCValAssign::LocInfo"); 211349cc55cSDimitry Andric case CCValAssign::Full: 212349cc55cSDimitry Andric break; 213349cc55cSDimitry Andric case CCValAssign::BCvt: 214349cc55cSDimitry Andric Val = DAG.getNode(ISD::BITCAST, DL, VA.getValVT(), Val); 215349cc55cSDimitry Andric break; 216349cc55cSDimitry Andric } 217349cc55cSDimitry Andric return Val; 218349cc55cSDimitry Andric } 219349cc55cSDimitry Andric 220349cc55cSDimitry Andric static SDValue unpackFromRegLoc(const CSKYSubtarget &Subtarget, 221349cc55cSDimitry Andric SelectionDAG &DAG, SDValue Chain, 222349cc55cSDimitry Andric const CCValAssign &VA, const SDLoc &DL) { 223349cc55cSDimitry Andric MachineFunction &MF = DAG.getMachineFunction(); 224349cc55cSDimitry Andric MachineRegisterInfo &RegInfo = MF.getRegInfo(); 225349cc55cSDimitry Andric EVT LocVT = VA.getLocVT(); 226349cc55cSDimitry Andric SDValue Val; 227349cc55cSDimitry Andric const TargetRegisterClass *RC; 228349cc55cSDimitry Andric 229349cc55cSDimitry Andric switch (LocVT.getSimpleVT().SimpleTy) { 230349cc55cSDimitry Andric default: 231349cc55cSDimitry Andric llvm_unreachable("Unexpected register type"); 232349cc55cSDimitry Andric case MVT::i32: 233349cc55cSDimitry Andric RC = &CSKY::GPRRegClass; 234349cc55cSDimitry Andric break; 23504eeddc0SDimitry Andric case MVT::f32: 23604eeddc0SDimitry Andric RC = Subtarget.hasFPUv2SingleFloat() ? &CSKY::sFPR32RegClass 23704eeddc0SDimitry Andric : &CSKY::FPR32RegClass; 23804eeddc0SDimitry Andric break; 23904eeddc0SDimitry Andric case MVT::f64: 24004eeddc0SDimitry Andric RC = Subtarget.hasFPUv2DoubleFloat() ? &CSKY::sFPR64RegClass 24104eeddc0SDimitry Andric : &CSKY::FPR64RegClass; 24204eeddc0SDimitry Andric break; 243349cc55cSDimitry Andric } 244349cc55cSDimitry Andric 245349cc55cSDimitry Andric Register VReg = RegInfo.createVirtualRegister(RC); 246349cc55cSDimitry Andric RegInfo.addLiveIn(VA.getLocReg(), VReg); 247349cc55cSDimitry Andric Val = DAG.getCopyFromReg(Chain, DL, VReg, LocVT); 248349cc55cSDimitry Andric 249349cc55cSDimitry Andric return convertLocVTToValVT(DAG, Val, VA, DL); 250349cc55cSDimitry Andric } 251349cc55cSDimitry Andric 252349cc55cSDimitry Andric static SDValue unpackFromMemLoc(SelectionDAG &DAG, SDValue Chain, 253349cc55cSDimitry Andric const CCValAssign &VA, const SDLoc &DL) { 254349cc55cSDimitry Andric MachineFunction &MF = DAG.getMachineFunction(); 255349cc55cSDimitry Andric MachineFrameInfo &MFI = MF.getFrameInfo(); 256349cc55cSDimitry Andric EVT LocVT = VA.getLocVT(); 257349cc55cSDimitry Andric EVT ValVT = VA.getValVT(); 258349cc55cSDimitry Andric EVT PtrVT = MVT::getIntegerVT(DAG.getDataLayout().getPointerSizeInBits(0)); 259349cc55cSDimitry Andric int FI = MFI.CreateFixedObject(ValVT.getSizeInBits() / 8, 260349cc55cSDimitry Andric VA.getLocMemOffset(), /*Immutable=*/true); 261349cc55cSDimitry Andric SDValue FIN = DAG.getFrameIndex(FI, PtrVT); 262349cc55cSDimitry Andric SDValue Val; 263349cc55cSDimitry Andric 264349cc55cSDimitry Andric ISD::LoadExtType ExtType; 265349cc55cSDimitry Andric switch (VA.getLocInfo()) { 266349cc55cSDimitry Andric default: 267349cc55cSDimitry Andric llvm_unreachable("Unexpected CCValAssign::LocInfo"); 268349cc55cSDimitry Andric case CCValAssign::Full: 269349cc55cSDimitry Andric case CCValAssign::BCvt: 270349cc55cSDimitry Andric ExtType = ISD::NON_EXTLOAD; 271349cc55cSDimitry Andric break; 272349cc55cSDimitry Andric } 273349cc55cSDimitry Andric Val = DAG.getExtLoad( 274349cc55cSDimitry Andric ExtType, DL, LocVT, Chain, FIN, 275349cc55cSDimitry Andric MachinePointerInfo::getFixedStack(DAG.getMachineFunction(), FI), ValVT); 276349cc55cSDimitry Andric return Val; 277349cc55cSDimitry Andric } 278349cc55cSDimitry Andric 27904eeddc0SDimitry Andric static SDValue unpack64(SelectionDAG &DAG, SDValue Chain, const CCValAssign &VA, 28004eeddc0SDimitry Andric const SDLoc &DL) { 28104eeddc0SDimitry Andric assert(VA.getLocVT() == MVT::i32 && 28204eeddc0SDimitry Andric (VA.getValVT() == MVT::f64 || VA.getValVT() == MVT::i64) && 28304eeddc0SDimitry Andric "Unexpected VA"); 28404eeddc0SDimitry Andric MachineFunction &MF = DAG.getMachineFunction(); 28504eeddc0SDimitry Andric MachineFrameInfo &MFI = MF.getFrameInfo(); 28604eeddc0SDimitry Andric MachineRegisterInfo &RegInfo = MF.getRegInfo(); 28704eeddc0SDimitry Andric 28804eeddc0SDimitry Andric if (VA.isMemLoc()) { 28904eeddc0SDimitry Andric // f64/i64 is passed on the stack. 29004eeddc0SDimitry Andric int FI = MFI.CreateFixedObject(8, VA.getLocMemOffset(), /*Immutable=*/true); 29104eeddc0SDimitry Andric SDValue FIN = DAG.getFrameIndex(FI, MVT::i32); 29204eeddc0SDimitry Andric return DAG.getLoad(VA.getValVT(), DL, Chain, FIN, 29304eeddc0SDimitry Andric MachinePointerInfo::getFixedStack(MF, FI)); 29404eeddc0SDimitry Andric } 29504eeddc0SDimitry Andric 29604eeddc0SDimitry Andric assert(VA.isRegLoc() && "Expected register VA assignment"); 29704eeddc0SDimitry Andric 29804eeddc0SDimitry Andric Register LoVReg = RegInfo.createVirtualRegister(&CSKY::GPRRegClass); 29904eeddc0SDimitry Andric RegInfo.addLiveIn(VA.getLocReg(), LoVReg); 30004eeddc0SDimitry Andric SDValue Lo = DAG.getCopyFromReg(Chain, DL, LoVReg, MVT::i32); 30104eeddc0SDimitry Andric SDValue Hi; 30204eeddc0SDimitry Andric if (VA.getLocReg() == CSKY::R3) { 30304eeddc0SDimitry Andric // Second half of f64/i64 is passed on the stack. 30404eeddc0SDimitry Andric int FI = MFI.CreateFixedObject(4, 0, /*Immutable=*/true); 30504eeddc0SDimitry Andric SDValue FIN = DAG.getFrameIndex(FI, MVT::i32); 30604eeddc0SDimitry Andric Hi = DAG.getLoad(MVT::i32, DL, Chain, FIN, 30704eeddc0SDimitry Andric MachinePointerInfo::getFixedStack(MF, FI)); 30804eeddc0SDimitry Andric } else { 30904eeddc0SDimitry Andric // Second half of f64/i64 is passed in another GPR. 31004eeddc0SDimitry Andric Register HiVReg = RegInfo.createVirtualRegister(&CSKY::GPRRegClass); 31104eeddc0SDimitry Andric RegInfo.addLiveIn(VA.getLocReg() + 1, HiVReg); 31204eeddc0SDimitry Andric Hi = DAG.getCopyFromReg(Chain, DL, HiVReg, MVT::i32); 31304eeddc0SDimitry Andric } 31404eeddc0SDimitry Andric return DAG.getNode(CSKYISD::BITCAST_FROM_LOHI, DL, VA.getValVT(), Lo, Hi); 31504eeddc0SDimitry Andric } 31604eeddc0SDimitry Andric 317349cc55cSDimitry Andric // Transform physical registers into virtual registers. 318349cc55cSDimitry Andric SDValue CSKYTargetLowering::LowerFormalArguments( 319349cc55cSDimitry Andric SDValue Chain, CallingConv::ID CallConv, bool IsVarArg, 320349cc55cSDimitry Andric const SmallVectorImpl<ISD::InputArg> &Ins, const SDLoc &DL, 321349cc55cSDimitry Andric SelectionDAG &DAG, SmallVectorImpl<SDValue> &InVals) const { 322349cc55cSDimitry Andric 323349cc55cSDimitry Andric switch (CallConv) { 324349cc55cSDimitry Andric default: 325349cc55cSDimitry Andric report_fatal_error("Unsupported calling convention"); 326349cc55cSDimitry Andric case CallingConv::C: 327349cc55cSDimitry Andric case CallingConv::Fast: 328349cc55cSDimitry Andric break; 329349cc55cSDimitry Andric } 330349cc55cSDimitry Andric 331349cc55cSDimitry Andric MachineFunction &MF = DAG.getMachineFunction(); 332349cc55cSDimitry Andric 333349cc55cSDimitry Andric // Used with vargs to acumulate store chains. 334349cc55cSDimitry Andric std::vector<SDValue> OutChains; 335349cc55cSDimitry Andric 336349cc55cSDimitry Andric // Assign locations to all of the incoming arguments. 337349cc55cSDimitry Andric SmallVector<CCValAssign, 16> ArgLocs; 338349cc55cSDimitry Andric CCState CCInfo(CallConv, IsVarArg, MF, ArgLocs, *DAG.getContext()); 339349cc55cSDimitry Andric 340349cc55cSDimitry Andric CCInfo.AnalyzeFormalArguments(Ins, CCAssignFnForCall(CallConv, IsVarArg)); 341349cc55cSDimitry Andric 342349cc55cSDimitry Andric for (unsigned i = 0, e = ArgLocs.size(); i != e; ++i) { 343349cc55cSDimitry Andric CCValAssign &VA = ArgLocs[i]; 344349cc55cSDimitry Andric SDValue ArgValue; 345349cc55cSDimitry Andric 34604eeddc0SDimitry Andric bool IsF64OnCSKY = VA.getLocVT() == MVT::i32 && VA.getValVT() == MVT::f64; 34704eeddc0SDimitry Andric 34804eeddc0SDimitry Andric if (IsF64OnCSKY) 34904eeddc0SDimitry Andric ArgValue = unpack64(DAG, Chain, VA, DL); 35004eeddc0SDimitry Andric else if (VA.isRegLoc()) 351349cc55cSDimitry Andric ArgValue = unpackFromRegLoc(Subtarget, DAG, Chain, VA, DL); 352349cc55cSDimitry Andric else 353349cc55cSDimitry Andric ArgValue = unpackFromMemLoc(DAG, Chain, VA, DL); 354349cc55cSDimitry Andric 355349cc55cSDimitry Andric InVals.push_back(ArgValue); 356349cc55cSDimitry Andric } 357349cc55cSDimitry Andric 358349cc55cSDimitry Andric if (IsVarArg) { 359349cc55cSDimitry Andric const unsigned XLenInBytes = 4; 360349cc55cSDimitry Andric const MVT XLenVT = MVT::i32; 361349cc55cSDimitry Andric 362349cc55cSDimitry Andric ArrayRef<MCPhysReg> ArgRegs = makeArrayRef(GPRArgRegs); 363349cc55cSDimitry Andric unsigned Idx = CCInfo.getFirstUnallocated(ArgRegs); 364349cc55cSDimitry Andric const TargetRegisterClass *RC = &CSKY::GPRRegClass; 365349cc55cSDimitry Andric MachineFrameInfo &MFI = MF.getFrameInfo(); 366349cc55cSDimitry Andric MachineRegisterInfo &RegInfo = MF.getRegInfo(); 367349cc55cSDimitry Andric CSKYMachineFunctionInfo *CSKYFI = MF.getInfo<CSKYMachineFunctionInfo>(); 368349cc55cSDimitry Andric 369349cc55cSDimitry Andric // Offset of the first variable argument from stack pointer, and size of 370349cc55cSDimitry Andric // the vararg save area. For now, the varargs save area is either zero or 371349cc55cSDimitry Andric // large enough to hold a0-a4. 372349cc55cSDimitry Andric int VaArgOffset, VarArgsSaveSize; 373349cc55cSDimitry Andric 374349cc55cSDimitry Andric // If all registers are allocated, then all varargs must be passed on the 375349cc55cSDimitry Andric // stack and we don't need to save any argregs. 376349cc55cSDimitry Andric if (ArgRegs.size() == Idx) { 377349cc55cSDimitry Andric VaArgOffset = CCInfo.getNextStackOffset(); 378349cc55cSDimitry Andric VarArgsSaveSize = 0; 379349cc55cSDimitry Andric } else { 380349cc55cSDimitry Andric VarArgsSaveSize = XLenInBytes * (ArgRegs.size() - Idx); 381349cc55cSDimitry Andric VaArgOffset = -VarArgsSaveSize; 382349cc55cSDimitry Andric } 383349cc55cSDimitry Andric 384349cc55cSDimitry Andric // Record the frame index of the first variable argument 385349cc55cSDimitry Andric // which is a value necessary to VASTART. 386349cc55cSDimitry Andric int FI = MFI.CreateFixedObject(XLenInBytes, VaArgOffset, true); 387349cc55cSDimitry Andric CSKYFI->setVarArgsFrameIndex(FI); 388349cc55cSDimitry Andric 389349cc55cSDimitry Andric // Copy the integer registers that may have been used for passing varargs 390349cc55cSDimitry Andric // to the vararg save area. 391349cc55cSDimitry Andric for (unsigned I = Idx; I < ArgRegs.size(); 392349cc55cSDimitry Andric ++I, VaArgOffset += XLenInBytes) { 393349cc55cSDimitry Andric const Register Reg = RegInfo.createVirtualRegister(RC); 394349cc55cSDimitry Andric RegInfo.addLiveIn(ArgRegs[I], Reg); 395349cc55cSDimitry Andric SDValue ArgValue = DAG.getCopyFromReg(Chain, DL, Reg, XLenVT); 396349cc55cSDimitry Andric FI = MFI.CreateFixedObject(XLenInBytes, VaArgOffset, true); 397349cc55cSDimitry Andric SDValue PtrOff = DAG.getFrameIndex(FI, getPointerTy(DAG.getDataLayout())); 398349cc55cSDimitry Andric SDValue Store = DAG.getStore(Chain, DL, ArgValue, PtrOff, 399349cc55cSDimitry Andric MachinePointerInfo::getFixedStack(MF, FI)); 400349cc55cSDimitry Andric cast<StoreSDNode>(Store.getNode()) 401349cc55cSDimitry Andric ->getMemOperand() 402349cc55cSDimitry Andric ->setValue((Value *)nullptr); 403349cc55cSDimitry Andric OutChains.push_back(Store); 404349cc55cSDimitry Andric } 405349cc55cSDimitry Andric CSKYFI->setVarArgsSaveSize(VarArgsSaveSize); 406349cc55cSDimitry Andric } 407349cc55cSDimitry Andric 408349cc55cSDimitry Andric // All stores are grouped in one node to allow the matching between 409349cc55cSDimitry Andric // the size of Ins and InVals. This only happens for vararg functions. 410349cc55cSDimitry Andric if (!OutChains.empty()) { 411349cc55cSDimitry Andric OutChains.push_back(Chain); 412349cc55cSDimitry Andric Chain = DAG.getNode(ISD::TokenFactor, DL, MVT::Other, OutChains); 413349cc55cSDimitry Andric } 414349cc55cSDimitry Andric 415349cc55cSDimitry Andric return Chain; 416349cc55cSDimitry Andric } 417349cc55cSDimitry Andric 418349cc55cSDimitry Andric bool CSKYTargetLowering::CanLowerReturn( 419349cc55cSDimitry Andric CallingConv::ID CallConv, MachineFunction &MF, bool IsVarArg, 420349cc55cSDimitry Andric const SmallVectorImpl<ISD::OutputArg> &Outs, LLVMContext &Context) const { 421349cc55cSDimitry Andric SmallVector<CCValAssign, 16> CSKYLocs; 422349cc55cSDimitry Andric CCState CCInfo(CallConv, IsVarArg, MF, CSKYLocs, Context); 423349cc55cSDimitry Andric return CCInfo.CheckReturn(Outs, CCAssignFnForReturn(CallConv, IsVarArg)); 424349cc55cSDimitry Andric } 425349cc55cSDimitry Andric 426349cc55cSDimitry Andric SDValue 427349cc55cSDimitry Andric CSKYTargetLowering::LowerReturn(SDValue Chain, CallingConv::ID CallConv, 428349cc55cSDimitry Andric bool IsVarArg, 429349cc55cSDimitry Andric const SmallVectorImpl<ISD::OutputArg> &Outs, 430349cc55cSDimitry Andric const SmallVectorImpl<SDValue> &OutVals, 431349cc55cSDimitry Andric const SDLoc &DL, SelectionDAG &DAG) const { 432349cc55cSDimitry Andric // Stores the assignment of the return value to a location. 433349cc55cSDimitry Andric SmallVector<CCValAssign, 16> CSKYLocs; 434349cc55cSDimitry Andric 435349cc55cSDimitry Andric // Info about the registers and stack slot. 436349cc55cSDimitry Andric CCState CCInfo(CallConv, IsVarArg, DAG.getMachineFunction(), CSKYLocs, 437349cc55cSDimitry Andric *DAG.getContext()); 438349cc55cSDimitry Andric CCInfo.AnalyzeReturn(Outs, CCAssignFnForReturn(CallConv, IsVarArg)); 439349cc55cSDimitry Andric 440349cc55cSDimitry Andric SDValue Glue; 441349cc55cSDimitry Andric SmallVector<SDValue, 4> RetOps(1, Chain); 442349cc55cSDimitry Andric 443349cc55cSDimitry Andric // Copy the result values into the output registers. 444349cc55cSDimitry Andric for (unsigned i = 0, e = CSKYLocs.size(); i < e; ++i) { 445349cc55cSDimitry Andric SDValue Val = OutVals[i]; 446349cc55cSDimitry Andric CCValAssign &VA = CSKYLocs[i]; 447349cc55cSDimitry Andric assert(VA.isRegLoc() && "Can only return in registers!"); 448349cc55cSDimitry Andric 449349cc55cSDimitry Andric bool IsF64OnCSKY = VA.getLocVT() == MVT::i32 && VA.getValVT() == MVT::f64; 450349cc55cSDimitry Andric 451349cc55cSDimitry Andric if (IsF64OnCSKY) { 452349cc55cSDimitry Andric 453349cc55cSDimitry Andric assert(VA.isRegLoc() && "Expected return via registers"); 454349cc55cSDimitry Andric SDValue Split64 = DAG.getNode(CSKYISD::BITCAST_TO_LOHI, DL, 455349cc55cSDimitry Andric DAG.getVTList(MVT::i32, MVT::i32), Val); 456349cc55cSDimitry Andric SDValue Lo = Split64.getValue(0); 457349cc55cSDimitry Andric SDValue Hi = Split64.getValue(1); 458349cc55cSDimitry Andric 459349cc55cSDimitry Andric Register RegLo = VA.getLocReg(); 460349cc55cSDimitry Andric assert(RegLo < CSKY::R31 && "Invalid register pair"); 461349cc55cSDimitry Andric Register RegHi = RegLo + 1; 462349cc55cSDimitry Andric 463349cc55cSDimitry Andric Chain = DAG.getCopyToReg(Chain, DL, RegLo, Lo, Glue); 464349cc55cSDimitry Andric Glue = Chain.getValue(1); 465349cc55cSDimitry Andric RetOps.push_back(DAG.getRegister(RegLo, MVT::i32)); 466349cc55cSDimitry Andric Chain = DAG.getCopyToReg(Chain, DL, RegHi, Hi, Glue); 467349cc55cSDimitry Andric Glue = Chain.getValue(1); 468349cc55cSDimitry Andric RetOps.push_back(DAG.getRegister(RegHi, MVT::i32)); 469349cc55cSDimitry Andric } else { 470349cc55cSDimitry Andric // Handle a 'normal' return. 471349cc55cSDimitry Andric Val = convertValVTToLocVT(DAG, Val, VA, DL); 472349cc55cSDimitry Andric Chain = DAG.getCopyToReg(Chain, DL, VA.getLocReg(), Val, Glue); 473349cc55cSDimitry Andric 474349cc55cSDimitry Andric // Guarantee that all emitted copies are stuck together. 475349cc55cSDimitry Andric Glue = Chain.getValue(1); 476349cc55cSDimitry Andric RetOps.push_back(DAG.getRegister(VA.getLocReg(), VA.getLocVT())); 477349cc55cSDimitry Andric } 478349cc55cSDimitry Andric } 479349cc55cSDimitry Andric 480349cc55cSDimitry Andric RetOps[0] = Chain; // Update chain. 481349cc55cSDimitry Andric 482349cc55cSDimitry Andric // Add the glue node if we have it. 483349cc55cSDimitry Andric if (Glue.getNode()) { 484349cc55cSDimitry Andric RetOps.push_back(Glue); 485349cc55cSDimitry Andric } 486349cc55cSDimitry Andric 487349cc55cSDimitry Andric // Interrupt service routines use different return instructions. 488349cc55cSDimitry Andric if (DAG.getMachineFunction().getFunction().hasFnAttribute("interrupt")) 489349cc55cSDimitry Andric return DAG.getNode(CSKYISD::NIR, DL, MVT::Other, RetOps); 490349cc55cSDimitry Andric 491349cc55cSDimitry Andric return DAG.getNode(CSKYISD::RET, DL, MVT::Other, RetOps); 492349cc55cSDimitry Andric } 493349cc55cSDimitry Andric 49404eeddc0SDimitry Andric // Lower a call to a callseq_start + CALL + callseq_end chain, and add input 49504eeddc0SDimitry Andric // and output parameter nodes. 49604eeddc0SDimitry Andric SDValue CSKYTargetLowering::LowerCall(CallLoweringInfo &CLI, 49704eeddc0SDimitry Andric SmallVectorImpl<SDValue> &InVals) const { 49804eeddc0SDimitry Andric SelectionDAG &DAG = CLI.DAG; 49904eeddc0SDimitry Andric SDLoc &DL = CLI.DL; 50004eeddc0SDimitry Andric SmallVectorImpl<ISD::OutputArg> &Outs = CLI.Outs; 50104eeddc0SDimitry Andric SmallVectorImpl<SDValue> &OutVals = CLI.OutVals; 50204eeddc0SDimitry Andric SmallVectorImpl<ISD::InputArg> &Ins = CLI.Ins; 50304eeddc0SDimitry Andric SDValue Chain = CLI.Chain; 50404eeddc0SDimitry Andric SDValue Callee = CLI.Callee; 50504eeddc0SDimitry Andric bool &IsTailCall = CLI.IsTailCall; 50604eeddc0SDimitry Andric CallingConv::ID CallConv = CLI.CallConv; 50704eeddc0SDimitry Andric bool IsVarArg = CLI.IsVarArg; 50804eeddc0SDimitry Andric EVT PtrVT = getPointerTy(DAG.getDataLayout()); 50904eeddc0SDimitry Andric MVT XLenVT = MVT::i32; 51004eeddc0SDimitry Andric 51104eeddc0SDimitry Andric MachineFunction &MF = DAG.getMachineFunction(); 51204eeddc0SDimitry Andric 51304eeddc0SDimitry Andric // Analyze the operands of the call, assigning locations to each operand. 51404eeddc0SDimitry Andric SmallVector<CCValAssign, 16> ArgLocs; 51504eeddc0SDimitry Andric CCState ArgCCInfo(CallConv, IsVarArg, MF, ArgLocs, *DAG.getContext()); 51604eeddc0SDimitry Andric 51704eeddc0SDimitry Andric ArgCCInfo.AnalyzeCallOperands(Outs, CCAssignFnForCall(CallConv, IsVarArg)); 51804eeddc0SDimitry Andric 51904eeddc0SDimitry Andric // Check if it's really possible to do a tail call. 52004eeddc0SDimitry Andric if (IsTailCall) 52104eeddc0SDimitry Andric IsTailCall = false; // TODO: TailCallOptimization; 52204eeddc0SDimitry Andric 52304eeddc0SDimitry Andric if (IsTailCall) 52404eeddc0SDimitry Andric ++NumTailCalls; 52504eeddc0SDimitry Andric else if (CLI.CB && CLI.CB->isMustTailCall()) 52604eeddc0SDimitry Andric report_fatal_error("failed to perform tail call elimination on a call " 52704eeddc0SDimitry Andric "site marked musttail"); 52804eeddc0SDimitry Andric 52904eeddc0SDimitry Andric // Get a count of how many bytes are to be pushed on the stack. 53004eeddc0SDimitry Andric unsigned NumBytes = ArgCCInfo.getNextStackOffset(); 53104eeddc0SDimitry Andric 53204eeddc0SDimitry Andric // Create local copies for byval args 53304eeddc0SDimitry Andric SmallVector<SDValue, 8> ByValArgs; 53404eeddc0SDimitry Andric for (unsigned i = 0, e = Outs.size(); i != e; ++i) { 53504eeddc0SDimitry Andric ISD::ArgFlagsTy Flags = Outs[i].Flags; 53604eeddc0SDimitry Andric if (!Flags.isByVal()) 53704eeddc0SDimitry Andric continue; 53804eeddc0SDimitry Andric 53904eeddc0SDimitry Andric SDValue Arg = OutVals[i]; 54004eeddc0SDimitry Andric unsigned Size = Flags.getByValSize(); 54104eeddc0SDimitry Andric Align Alignment = Flags.getNonZeroByValAlign(); 54204eeddc0SDimitry Andric 54304eeddc0SDimitry Andric int FI = 54404eeddc0SDimitry Andric MF.getFrameInfo().CreateStackObject(Size, Alignment, /*isSS=*/false); 54504eeddc0SDimitry Andric SDValue FIPtr = DAG.getFrameIndex(FI, getPointerTy(DAG.getDataLayout())); 54604eeddc0SDimitry Andric SDValue SizeNode = DAG.getConstant(Size, DL, XLenVT); 54704eeddc0SDimitry Andric 54804eeddc0SDimitry Andric Chain = DAG.getMemcpy(Chain, DL, FIPtr, Arg, SizeNode, Alignment, 54904eeddc0SDimitry Andric /*IsVolatile=*/false, 55004eeddc0SDimitry Andric /*AlwaysInline=*/false, IsTailCall, 55104eeddc0SDimitry Andric MachinePointerInfo(), MachinePointerInfo()); 55204eeddc0SDimitry Andric ByValArgs.push_back(FIPtr); 55304eeddc0SDimitry Andric } 55404eeddc0SDimitry Andric 55504eeddc0SDimitry Andric if (!IsTailCall) 55604eeddc0SDimitry Andric Chain = DAG.getCALLSEQ_START(Chain, NumBytes, 0, CLI.DL); 55704eeddc0SDimitry Andric 55804eeddc0SDimitry Andric // Copy argument values to their designated locations. 55904eeddc0SDimitry Andric SmallVector<std::pair<Register, SDValue>, 8> RegsToPass; 56004eeddc0SDimitry Andric SmallVector<SDValue, 8> MemOpChains; 56104eeddc0SDimitry Andric SDValue StackPtr; 56204eeddc0SDimitry Andric for (unsigned i = 0, j = 0, e = ArgLocs.size(); i != e; ++i) { 56304eeddc0SDimitry Andric CCValAssign &VA = ArgLocs[i]; 56404eeddc0SDimitry Andric SDValue ArgValue = OutVals[i]; 56504eeddc0SDimitry Andric ISD::ArgFlagsTy Flags = Outs[i].Flags; 56604eeddc0SDimitry Andric 56704eeddc0SDimitry Andric bool IsF64OnCSKY = VA.getLocVT() == MVT::i32 && VA.getValVT() == MVT::f64; 56804eeddc0SDimitry Andric 56904eeddc0SDimitry Andric if (IsF64OnCSKY && VA.isRegLoc()) { 57004eeddc0SDimitry Andric SDValue Split64 = 57104eeddc0SDimitry Andric DAG.getNode(CSKYISD::BITCAST_TO_LOHI, DL, 57204eeddc0SDimitry Andric DAG.getVTList(MVT::i32, MVT::i32), ArgValue); 57304eeddc0SDimitry Andric SDValue Lo = Split64.getValue(0); 57404eeddc0SDimitry Andric SDValue Hi = Split64.getValue(1); 57504eeddc0SDimitry Andric 57604eeddc0SDimitry Andric Register RegLo = VA.getLocReg(); 57704eeddc0SDimitry Andric RegsToPass.push_back(std::make_pair(RegLo, Lo)); 57804eeddc0SDimitry Andric 57904eeddc0SDimitry Andric if (RegLo == CSKY::R3) { 58004eeddc0SDimitry Andric // Second half of f64/i64 is passed on the stack. 58104eeddc0SDimitry Andric // Work out the address of the stack slot. 58204eeddc0SDimitry Andric if (!StackPtr.getNode()) 58304eeddc0SDimitry Andric StackPtr = DAG.getCopyFromReg(Chain, DL, CSKY::R14, PtrVT); 58404eeddc0SDimitry Andric // Emit the store. 58504eeddc0SDimitry Andric MemOpChains.push_back( 58604eeddc0SDimitry Andric DAG.getStore(Chain, DL, Hi, StackPtr, MachinePointerInfo())); 58704eeddc0SDimitry Andric } else { 58804eeddc0SDimitry Andric // Second half of f64/i64 is passed in another GPR. 58904eeddc0SDimitry Andric assert(RegLo < CSKY::R31 && "Invalid register pair"); 59004eeddc0SDimitry Andric Register RegHigh = RegLo + 1; 59104eeddc0SDimitry Andric RegsToPass.push_back(std::make_pair(RegHigh, Hi)); 59204eeddc0SDimitry Andric } 59304eeddc0SDimitry Andric continue; 59404eeddc0SDimitry Andric } 59504eeddc0SDimitry Andric 59604eeddc0SDimitry Andric ArgValue = convertValVTToLocVT(DAG, ArgValue, VA, DL); 59704eeddc0SDimitry Andric 59804eeddc0SDimitry Andric // Use local copy if it is a byval arg. 59904eeddc0SDimitry Andric if (Flags.isByVal()) 60004eeddc0SDimitry Andric ArgValue = ByValArgs[j++]; 60104eeddc0SDimitry Andric 60204eeddc0SDimitry Andric if (VA.isRegLoc()) { 60304eeddc0SDimitry Andric // Queue up the argument copies and emit them at the end. 60404eeddc0SDimitry Andric RegsToPass.push_back(std::make_pair(VA.getLocReg(), ArgValue)); 60504eeddc0SDimitry Andric } else { 60604eeddc0SDimitry Andric assert(VA.isMemLoc() && "Argument not register or memory"); 60704eeddc0SDimitry Andric assert(!IsTailCall && "Tail call not allowed if stack is used " 60804eeddc0SDimitry Andric "for passing parameters"); 60904eeddc0SDimitry Andric 61004eeddc0SDimitry Andric // Work out the address of the stack slot. 61104eeddc0SDimitry Andric if (!StackPtr.getNode()) 61204eeddc0SDimitry Andric StackPtr = DAG.getCopyFromReg(Chain, DL, CSKY::R14, PtrVT); 61304eeddc0SDimitry Andric SDValue Address = 61404eeddc0SDimitry Andric DAG.getNode(ISD::ADD, DL, PtrVT, StackPtr, 61504eeddc0SDimitry Andric DAG.getIntPtrConstant(VA.getLocMemOffset(), DL)); 61604eeddc0SDimitry Andric 61704eeddc0SDimitry Andric // Emit the store. 61804eeddc0SDimitry Andric MemOpChains.push_back( 61904eeddc0SDimitry Andric DAG.getStore(Chain, DL, ArgValue, Address, MachinePointerInfo())); 62004eeddc0SDimitry Andric } 62104eeddc0SDimitry Andric } 62204eeddc0SDimitry Andric 62304eeddc0SDimitry Andric // Join the stores, which are independent of one another. 62404eeddc0SDimitry Andric if (!MemOpChains.empty()) 62504eeddc0SDimitry Andric Chain = DAG.getNode(ISD::TokenFactor, DL, MVT::Other, MemOpChains); 62604eeddc0SDimitry Andric 62704eeddc0SDimitry Andric SDValue Glue; 62804eeddc0SDimitry Andric 62904eeddc0SDimitry Andric // Build a sequence of copy-to-reg nodes, chained and glued together. 63004eeddc0SDimitry Andric for (auto &Reg : RegsToPass) { 63104eeddc0SDimitry Andric Chain = DAG.getCopyToReg(Chain, DL, Reg.first, Reg.second, Glue); 63204eeddc0SDimitry Andric Glue = Chain.getValue(1); 63304eeddc0SDimitry Andric } 63404eeddc0SDimitry Andric 63504eeddc0SDimitry Andric SmallVector<SDValue, 8> Ops; 63604eeddc0SDimitry Andric EVT Ty = getPointerTy(DAG.getDataLayout()); 63704eeddc0SDimitry Andric bool IsRegCall = false; 63804eeddc0SDimitry Andric 63904eeddc0SDimitry Andric Ops.push_back(Chain); 64004eeddc0SDimitry Andric 64104eeddc0SDimitry Andric if (GlobalAddressSDNode *S = dyn_cast<GlobalAddressSDNode>(Callee)) { 64204eeddc0SDimitry Andric const GlobalValue *GV = S->getGlobal(); 64304eeddc0SDimitry Andric bool IsLocal = 64404eeddc0SDimitry Andric getTargetMachine().shouldAssumeDSOLocal(*GV->getParent(), GV); 64504eeddc0SDimitry Andric 64604eeddc0SDimitry Andric if (isPositionIndependent() || !Subtarget.has2E3()) { 64704eeddc0SDimitry Andric IsRegCall = true; 64804eeddc0SDimitry Andric Ops.push_back(getAddr<GlobalAddressSDNode, true>(S, DAG, IsLocal)); 64904eeddc0SDimitry Andric } else { 65004eeddc0SDimitry Andric Ops.push_back(getTargetNode(cast<GlobalAddressSDNode>(Callee), DL, Ty, 65104eeddc0SDimitry Andric DAG, CSKYII::MO_None)); 65204eeddc0SDimitry Andric Ops.push_back(getTargetConstantPoolValue( 65304eeddc0SDimitry Andric cast<GlobalAddressSDNode>(Callee), Ty, DAG, CSKYII::MO_None)); 65404eeddc0SDimitry Andric } 65504eeddc0SDimitry Andric } else if (ExternalSymbolSDNode *S = dyn_cast<ExternalSymbolSDNode>(Callee)) { 65604eeddc0SDimitry Andric bool IsLocal = getTargetMachine().shouldAssumeDSOLocal( 65704eeddc0SDimitry Andric *MF.getFunction().getParent(), nullptr); 65804eeddc0SDimitry Andric 65904eeddc0SDimitry Andric if (isPositionIndependent() || !Subtarget.has2E3()) { 66004eeddc0SDimitry Andric IsRegCall = true; 66104eeddc0SDimitry Andric Ops.push_back(getAddr<ExternalSymbolSDNode, true>(S, DAG, IsLocal)); 66204eeddc0SDimitry Andric } else { 66304eeddc0SDimitry Andric Ops.push_back(getTargetNode(cast<ExternalSymbolSDNode>(Callee), DL, Ty, 66404eeddc0SDimitry Andric DAG, CSKYII::MO_None)); 66504eeddc0SDimitry Andric Ops.push_back(getTargetConstantPoolValue( 66604eeddc0SDimitry Andric cast<ExternalSymbolSDNode>(Callee), Ty, DAG, CSKYII::MO_None)); 66704eeddc0SDimitry Andric } 66804eeddc0SDimitry Andric } else { 66904eeddc0SDimitry Andric IsRegCall = true; 67004eeddc0SDimitry Andric Ops.push_back(Callee); 67104eeddc0SDimitry Andric } 67204eeddc0SDimitry Andric 67304eeddc0SDimitry Andric // Add argument registers to the end of the list so that they are 67404eeddc0SDimitry Andric // known live into the call. 67504eeddc0SDimitry Andric for (auto &Reg : RegsToPass) 67604eeddc0SDimitry Andric Ops.push_back(DAG.getRegister(Reg.first, Reg.second.getValueType())); 67704eeddc0SDimitry Andric 67804eeddc0SDimitry Andric if (!IsTailCall) { 67904eeddc0SDimitry Andric // Add a register mask operand representing the call-preserved registers. 68004eeddc0SDimitry Andric const TargetRegisterInfo *TRI = Subtarget.getRegisterInfo(); 68104eeddc0SDimitry Andric const uint32_t *Mask = TRI->getCallPreservedMask(MF, CallConv); 68204eeddc0SDimitry Andric assert(Mask && "Missing call preserved mask for calling convention"); 68304eeddc0SDimitry Andric Ops.push_back(DAG.getRegisterMask(Mask)); 68404eeddc0SDimitry Andric } 68504eeddc0SDimitry Andric 68604eeddc0SDimitry Andric // Glue the call to the argument copies, if any. 68704eeddc0SDimitry Andric if (Glue.getNode()) 68804eeddc0SDimitry Andric Ops.push_back(Glue); 68904eeddc0SDimitry Andric 69004eeddc0SDimitry Andric // Emit the call. 69104eeddc0SDimitry Andric SDVTList NodeTys = DAG.getVTList(MVT::Other, MVT::Glue); 69204eeddc0SDimitry Andric 69304eeddc0SDimitry Andric if (IsTailCall) { 69404eeddc0SDimitry Andric MF.getFrameInfo().setHasTailCall(); 69504eeddc0SDimitry Andric return DAG.getNode(IsRegCall ? CSKYISD::TAILReg : CSKYISD::TAIL, DL, 69604eeddc0SDimitry Andric NodeTys, Ops); 69704eeddc0SDimitry Andric } 69804eeddc0SDimitry Andric 69904eeddc0SDimitry Andric Chain = DAG.getNode(IsRegCall ? CSKYISD::CALLReg : CSKYISD::CALL, DL, NodeTys, 70004eeddc0SDimitry Andric Ops); 70104eeddc0SDimitry Andric DAG.addNoMergeSiteInfo(Chain.getNode(), CLI.NoMerge); 70204eeddc0SDimitry Andric Glue = Chain.getValue(1); 70304eeddc0SDimitry Andric 70404eeddc0SDimitry Andric // Mark the end of the call, which is glued to the call itself. 70504eeddc0SDimitry Andric Chain = DAG.getCALLSEQ_END(Chain, DAG.getConstant(NumBytes, DL, PtrVT, true), 70604eeddc0SDimitry Andric DAG.getConstant(0, DL, PtrVT, true), Glue, DL); 70704eeddc0SDimitry Andric Glue = Chain.getValue(1); 70804eeddc0SDimitry Andric 70904eeddc0SDimitry Andric // Assign locations to each value returned by this call. 71004eeddc0SDimitry Andric SmallVector<CCValAssign, 16> CSKYLocs; 71104eeddc0SDimitry Andric CCState RetCCInfo(CallConv, IsVarArg, MF, CSKYLocs, *DAG.getContext()); 71204eeddc0SDimitry Andric RetCCInfo.AnalyzeCallResult(Ins, CCAssignFnForReturn(CallConv, IsVarArg)); 71304eeddc0SDimitry Andric 71404eeddc0SDimitry Andric // Copy all of the result registers out of their specified physreg. 71504eeddc0SDimitry Andric for (auto &VA : CSKYLocs) { 71604eeddc0SDimitry Andric // Copy the value out 71704eeddc0SDimitry Andric SDValue RetValue = 71804eeddc0SDimitry Andric DAG.getCopyFromReg(Chain, DL, VA.getLocReg(), VA.getLocVT(), Glue); 71904eeddc0SDimitry Andric // Glue the RetValue to the end of the call sequence 72004eeddc0SDimitry Andric Chain = RetValue.getValue(1); 72104eeddc0SDimitry Andric Glue = RetValue.getValue(2); 72204eeddc0SDimitry Andric 72304eeddc0SDimitry Andric bool IsF64OnCSKY = VA.getLocVT() == MVT::i32 && VA.getValVT() == MVT::f64; 72404eeddc0SDimitry Andric 72504eeddc0SDimitry Andric if (IsF64OnCSKY) { 72604eeddc0SDimitry Andric assert(VA.getLocReg() == GPRArgRegs[0] && "Unexpected reg assignment"); 72704eeddc0SDimitry Andric SDValue RetValue2 = 72804eeddc0SDimitry Andric DAG.getCopyFromReg(Chain, DL, GPRArgRegs[1], MVT::i32, Glue); 72904eeddc0SDimitry Andric Chain = RetValue2.getValue(1); 73004eeddc0SDimitry Andric Glue = RetValue2.getValue(2); 73104eeddc0SDimitry Andric RetValue = DAG.getNode(CSKYISD::BITCAST_FROM_LOHI, DL, VA.getValVT(), 73204eeddc0SDimitry Andric RetValue, RetValue2); 73304eeddc0SDimitry Andric } 73404eeddc0SDimitry Andric 73504eeddc0SDimitry Andric RetValue = convertLocVTToValVT(DAG, RetValue, VA, DL); 73604eeddc0SDimitry Andric 73704eeddc0SDimitry Andric InVals.push_back(RetValue); 73804eeddc0SDimitry Andric } 73904eeddc0SDimitry Andric 74004eeddc0SDimitry Andric return Chain; 74104eeddc0SDimitry Andric } 74204eeddc0SDimitry Andric 743349cc55cSDimitry Andric CCAssignFn *CSKYTargetLowering::CCAssignFnForReturn(CallingConv::ID CC, 744349cc55cSDimitry Andric bool IsVarArg) const { 745349cc55cSDimitry Andric if (IsVarArg || !Subtarget.useHardFloatABI()) 746349cc55cSDimitry Andric return RetCC_CSKY_ABIV2_SOFT; 747349cc55cSDimitry Andric else 748349cc55cSDimitry Andric return RetCC_CSKY_ABIV2_FP; 749349cc55cSDimitry Andric } 750349cc55cSDimitry Andric 751349cc55cSDimitry Andric CCAssignFn *CSKYTargetLowering::CCAssignFnForCall(CallingConv::ID CC, 752349cc55cSDimitry Andric bool IsVarArg) const { 753349cc55cSDimitry Andric if (IsVarArg || !Subtarget.useHardFloatABI()) 754349cc55cSDimitry Andric return CC_CSKY_ABIV2_SOFT; 755349cc55cSDimitry Andric else 756349cc55cSDimitry Andric return CC_CSKY_ABIV2_FP; 757349cc55cSDimitry Andric } 758349cc55cSDimitry Andric 75904eeddc0SDimitry Andric static CSKYCP::CSKYCPModifier getModifier(unsigned Flags) { 76004eeddc0SDimitry Andric 76104eeddc0SDimitry Andric if (Flags == CSKYII::MO_ADDR32) 76204eeddc0SDimitry Andric return CSKYCP::ADDR; 76304eeddc0SDimitry Andric else if (Flags == CSKYII::MO_GOT32) 76404eeddc0SDimitry Andric return CSKYCP::GOT; 76504eeddc0SDimitry Andric else if (Flags == CSKYII::MO_GOTOFF) 76604eeddc0SDimitry Andric return CSKYCP::GOTOFF; 76704eeddc0SDimitry Andric else if (Flags == CSKYII::MO_PLT32) 76804eeddc0SDimitry Andric return CSKYCP::PLT; 76904eeddc0SDimitry Andric else if (Flags == CSKYII::MO_None) 77004eeddc0SDimitry Andric return CSKYCP::NO_MOD; 77104eeddc0SDimitry Andric else 77204eeddc0SDimitry Andric assert(0 && "unknown CSKYII Modifier"); 77304eeddc0SDimitry Andric return CSKYCP::NO_MOD; 77404eeddc0SDimitry Andric } 77504eeddc0SDimitry Andric 77604eeddc0SDimitry Andric SDValue CSKYTargetLowering::getTargetConstantPoolValue(GlobalAddressSDNode *N, 77704eeddc0SDimitry Andric EVT Ty, 77804eeddc0SDimitry Andric SelectionDAG &DAG, 77904eeddc0SDimitry Andric unsigned Flags) const { 78004eeddc0SDimitry Andric CSKYConstantPoolValue *CPV = CSKYConstantPoolConstant::Create( 78104eeddc0SDimitry Andric N->getGlobal(), CSKYCP::CPValue, 0, getModifier(Flags), false); 78204eeddc0SDimitry Andric 78304eeddc0SDimitry Andric return DAG.getTargetConstantPool(CPV, Ty); 78404eeddc0SDimitry Andric } 78504eeddc0SDimitry Andric 786*81ad6265SDimitry Andric CSKYTargetLowering::ConstraintType 787*81ad6265SDimitry Andric CSKYTargetLowering::getConstraintType(StringRef Constraint) const { 788*81ad6265SDimitry Andric if (Constraint.size() == 1) { 789*81ad6265SDimitry Andric switch (Constraint[0]) { 790*81ad6265SDimitry Andric default: 791*81ad6265SDimitry Andric break; 792*81ad6265SDimitry Andric case 'a': 793*81ad6265SDimitry Andric case 'b': 794*81ad6265SDimitry Andric case 'v': 795*81ad6265SDimitry Andric case 'w': 796*81ad6265SDimitry Andric case 'y': 797*81ad6265SDimitry Andric return C_RegisterClass; 798*81ad6265SDimitry Andric case 'c': 799*81ad6265SDimitry Andric case 'l': 800*81ad6265SDimitry Andric case 'h': 801*81ad6265SDimitry Andric case 'z': 802*81ad6265SDimitry Andric return C_Register; 803*81ad6265SDimitry Andric } 804*81ad6265SDimitry Andric } 805*81ad6265SDimitry Andric return TargetLowering::getConstraintType(Constraint); 806*81ad6265SDimitry Andric } 807*81ad6265SDimitry Andric 808*81ad6265SDimitry Andric std::pair<unsigned, const TargetRegisterClass *> 809*81ad6265SDimitry Andric CSKYTargetLowering::getRegForInlineAsmConstraint(const TargetRegisterInfo *TRI, 810*81ad6265SDimitry Andric StringRef Constraint, 811*81ad6265SDimitry Andric MVT VT) const { 812*81ad6265SDimitry Andric if (Constraint.size() == 1) { 813*81ad6265SDimitry Andric switch (Constraint[0]) { 814*81ad6265SDimitry Andric case 'r': 815*81ad6265SDimitry Andric return std::make_pair(0U, &CSKY::GPRRegClass); 816*81ad6265SDimitry Andric case 'a': 817*81ad6265SDimitry Andric return std::make_pair(0U, &CSKY::mGPRRegClass); 818*81ad6265SDimitry Andric case 'b': 819*81ad6265SDimitry Andric return std::make_pair(0U, &CSKY::sGPRRegClass); 820*81ad6265SDimitry Andric case 'z': 821*81ad6265SDimitry Andric return std::make_pair(CSKY::R14, &CSKY::GPRRegClass); 822*81ad6265SDimitry Andric case 'c': 823*81ad6265SDimitry Andric return std::make_pair(CSKY::C, &CSKY::CARRYRegClass); 824*81ad6265SDimitry Andric case 'w': 825*81ad6265SDimitry Andric if ((Subtarget.hasFPUv2SingleFloat() || 826*81ad6265SDimitry Andric Subtarget.hasFPUv3SingleFloat()) && 827*81ad6265SDimitry Andric VT == MVT::f32) 828*81ad6265SDimitry Andric return std::make_pair(0U, &CSKY::sFPR32RegClass); 829*81ad6265SDimitry Andric if ((Subtarget.hasFPUv2DoubleFloat() || 830*81ad6265SDimitry Andric Subtarget.hasFPUv3DoubleFloat()) && 831*81ad6265SDimitry Andric VT == MVT::f64) 832*81ad6265SDimitry Andric return std::make_pair(0U, &CSKY::sFPR64RegClass); 833*81ad6265SDimitry Andric break; 834*81ad6265SDimitry Andric case 'v': 835*81ad6265SDimitry Andric if (Subtarget.hasFPUv2SingleFloat() && VT == MVT::f32) 836*81ad6265SDimitry Andric return std::make_pair(0U, &CSKY::sFPR32RegClass); 837*81ad6265SDimitry Andric if (Subtarget.hasFPUv3SingleFloat() && VT == MVT::f32) 838*81ad6265SDimitry Andric return std::make_pair(0U, &CSKY::FPR32RegClass); 839*81ad6265SDimitry Andric if (Subtarget.hasFPUv2DoubleFloat() && VT == MVT::f64) 840*81ad6265SDimitry Andric return std::make_pair(0U, &CSKY::sFPR64RegClass); 841*81ad6265SDimitry Andric if (Subtarget.hasFPUv3DoubleFloat() && VT == MVT::f64) 842*81ad6265SDimitry Andric return std::make_pair(0U, &CSKY::FPR64RegClass); 843*81ad6265SDimitry Andric break; 844*81ad6265SDimitry Andric default: 845*81ad6265SDimitry Andric break; 846*81ad6265SDimitry Andric } 847*81ad6265SDimitry Andric } 848*81ad6265SDimitry Andric 849*81ad6265SDimitry Andric if (Constraint == "{c}") 850*81ad6265SDimitry Andric return std::make_pair(CSKY::C, &CSKY::CARRYRegClass); 851*81ad6265SDimitry Andric 852*81ad6265SDimitry Andric // Clang will correctly decode the usage of register name aliases into their 853*81ad6265SDimitry Andric // official names. However, other frontends like `rustc` do not. This allows 854*81ad6265SDimitry Andric // users of these frontends to use the ABI names for registers in LLVM-style 855*81ad6265SDimitry Andric // register constraints. 856*81ad6265SDimitry Andric unsigned XRegFromAlias = StringSwitch<unsigned>(Constraint.lower()) 857*81ad6265SDimitry Andric .Case("{a0}", CSKY::R0) 858*81ad6265SDimitry Andric .Case("{a1}", CSKY::R1) 859*81ad6265SDimitry Andric .Case("{a2}", CSKY::R2) 860*81ad6265SDimitry Andric .Case("{a3}", CSKY::R3) 861*81ad6265SDimitry Andric .Case("{l0}", CSKY::R4) 862*81ad6265SDimitry Andric .Case("{l1}", CSKY::R5) 863*81ad6265SDimitry Andric .Case("{l2}", CSKY::R6) 864*81ad6265SDimitry Andric .Case("{l3}", CSKY::R7) 865*81ad6265SDimitry Andric .Case("{l4}", CSKY::R8) 866*81ad6265SDimitry Andric .Case("{l5}", CSKY::R9) 867*81ad6265SDimitry Andric .Case("{l6}", CSKY::R10) 868*81ad6265SDimitry Andric .Case("{l7}", CSKY::R11) 869*81ad6265SDimitry Andric .Case("{t0}", CSKY::R12) 870*81ad6265SDimitry Andric .Case("{t1}", CSKY::R13) 871*81ad6265SDimitry Andric .Case("{sp}", CSKY::R14) 872*81ad6265SDimitry Andric .Case("{lr}", CSKY::R15) 873*81ad6265SDimitry Andric .Case("{l8}", CSKY::R16) 874*81ad6265SDimitry Andric .Case("{l9}", CSKY::R17) 875*81ad6265SDimitry Andric .Case("{t2}", CSKY::R18) 876*81ad6265SDimitry Andric .Case("{t3}", CSKY::R19) 877*81ad6265SDimitry Andric .Case("{t4}", CSKY::R20) 878*81ad6265SDimitry Andric .Case("{t5}", CSKY::R21) 879*81ad6265SDimitry Andric .Case("{t6}", CSKY::R22) 880*81ad6265SDimitry Andric .Cases("{t7}", "{fp}", CSKY::R23) 881*81ad6265SDimitry Andric .Cases("{t8}", "{top}", CSKY::R24) 882*81ad6265SDimitry Andric .Cases("{t9}", "{bsp}", CSKY::R25) 883*81ad6265SDimitry Andric .Case("{r26}", CSKY::R26) 884*81ad6265SDimitry Andric .Case("{r27}", CSKY::R27) 885*81ad6265SDimitry Andric .Cases("{gb}", "{rgb}", "{rdb}", CSKY::R28) 886*81ad6265SDimitry Andric .Cases("{tb}", "{rtb}", CSKY::R29) 887*81ad6265SDimitry Andric .Case("{svbr}", CSKY::R30) 888*81ad6265SDimitry Andric .Case("{tls}", CSKY::R31) 889*81ad6265SDimitry Andric .Default(CSKY::NoRegister); 890*81ad6265SDimitry Andric 891*81ad6265SDimitry Andric if (XRegFromAlias != CSKY::NoRegister) 892*81ad6265SDimitry Andric return std::make_pair(XRegFromAlias, &CSKY::GPRRegClass); 893*81ad6265SDimitry Andric 894*81ad6265SDimitry Andric // Since TargetLowering::getRegForInlineAsmConstraint uses the name of the 895*81ad6265SDimitry Andric // TableGen record rather than the AsmName to choose registers for InlineAsm 896*81ad6265SDimitry Andric // constraints, plus we want to match those names to the widest floating point 897*81ad6265SDimitry Andric // register type available, manually select floating point registers here. 898*81ad6265SDimitry Andric // 899*81ad6265SDimitry Andric // The second case is the ABI name of the register, so that frontends can also 900*81ad6265SDimitry Andric // use the ABI names in register constraint lists. 901*81ad6265SDimitry Andric if (Subtarget.useHardFloat()) { 902*81ad6265SDimitry Andric unsigned FReg = StringSwitch<unsigned>(Constraint.lower()) 903*81ad6265SDimitry Andric .Cases("{fr0}", "{vr0}", CSKY::F0_32) 904*81ad6265SDimitry Andric .Cases("{fr1}", "{vr1}", CSKY::F1_32) 905*81ad6265SDimitry Andric .Cases("{fr2}", "{vr2}", CSKY::F2_32) 906*81ad6265SDimitry Andric .Cases("{fr3}", "{vr3}", CSKY::F3_32) 907*81ad6265SDimitry Andric .Cases("{fr4}", "{vr4}", CSKY::F4_32) 908*81ad6265SDimitry Andric .Cases("{fr5}", "{vr5}", CSKY::F5_32) 909*81ad6265SDimitry Andric .Cases("{fr6}", "{vr6}", CSKY::F6_32) 910*81ad6265SDimitry Andric .Cases("{fr7}", "{vr7}", CSKY::F7_32) 911*81ad6265SDimitry Andric .Cases("{fr8}", "{vr8}", CSKY::F8_32) 912*81ad6265SDimitry Andric .Cases("{fr9}", "{vr9}", CSKY::F9_32) 913*81ad6265SDimitry Andric .Cases("{fr10}", "{vr10}", CSKY::F10_32) 914*81ad6265SDimitry Andric .Cases("{fr11}", "{vr11}", CSKY::F11_32) 915*81ad6265SDimitry Andric .Cases("{fr12}", "{vr12}", CSKY::F12_32) 916*81ad6265SDimitry Andric .Cases("{fr13}", "{vr13}", CSKY::F13_32) 917*81ad6265SDimitry Andric .Cases("{fr14}", "{vr14}", CSKY::F14_32) 918*81ad6265SDimitry Andric .Cases("{fr15}", "{vr15}", CSKY::F15_32) 919*81ad6265SDimitry Andric .Cases("{fr16}", "{vr16}", CSKY::F16_32) 920*81ad6265SDimitry Andric .Cases("{fr17}", "{vr17}", CSKY::F17_32) 921*81ad6265SDimitry Andric .Cases("{fr18}", "{vr18}", CSKY::F18_32) 922*81ad6265SDimitry Andric .Cases("{fr19}", "{vr19}", CSKY::F19_32) 923*81ad6265SDimitry Andric .Cases("{fr20}", "{vr20}", CSKY::F20_32) 924*81ad6265SDimitry Andric .Cases("{fr21}", "{vr21}", CSKY::F21_32) 925*81ad6265SDimitry Andric .Cases("{fr22}", "{vr22}", CSKY::F22_32) 926*81ad6265SDimitry Andric .Cases("{fr23}", "{vr23}", CSKY::F23_32) 927*81ad6265SDimitry Andric .Cases("{fr24}", "{vr24}", CSKY::F24_32) 928*81ad6265SDimitry Andric .Cases("{fr25}", "{vr25}", CSKY::F25_32) 929*81ad6265SDimitry Andric .Cases("{fr26}", "{vr26}", CSKY::F26_32) 930*81ad6265SDimitry Andric .Cases("{fr27}", "{vr27}", CSKY::F27_32) 931*81ad6265SDimitry Andric .Cases("{fr28}", "{vr28}", CSKY::F28_32) 932*81ad6265SDimitry Andric .Cases("{fr29}", "{vr29}", CSKY::F29_32) 933*81ad6265SDimitry Andric .Cases("{fr30}", "{vr30}", CSKY::F30_32) 934*81ad6265SDimitry Andric .Cases("{fr31}", "{vr31}", CSKY::F31_32) 935*81ad6265SDimitry Andric .Default(CSKY::NoRegister); 936*81ad6265SDimitry Andric if (FReg != CSKY::NoRegister) { 937*81ad6265SDimitry Andric assert(CSKY::F0_32 <= FReg && FReg <= CSKY::F31_32 && "Unknown fp-reg"); 938*81ad6265SDimitry Andric unsigned RegNo = FReg - CSKY::F0_32; 939*81ad6265SDimitry Andric unsigned DReg = CSKY::F0_64 + RegNo; 940*81ad6265SDimitry Andric 941*81ad6265SDimitry Andric if (Subtarget.hasFPUv2DoubleFloat()) 942*81ad6265SDimitry Andric return std::make_pair(DReg, &CSKY::sFPR64RegClass); 943*81ad6265SDimitry Andric else if (Subtarget.hasFPUv3DoubleFloat()) 944*81ad6265SDimitry Andric return std::make_pair(DReg, &CSKY::FPR64RegClass); 945*81ad6265SDimitry Andric else if (Subtarget.hasFPUv2SingleFloat()) 946*81ad6265SDimitry Andric return std::make_pair(FReg, &CSKY::sFPR32RegClass); 947*81ad6265SDimitry Andric else if (Subtarget.hasFPUv3SingleFloat()) 948*81ad6265SDimitry Andric return std::make_pair(FReg, &CSKY::FPR32RegClass); 949*81ad6265SDimitry Andric } 950*81ad6265SDimitry Andric } 951*81ad6265SDimitry Andric 952*81ad6265SDimitry Andric return TargetLowering::getRegForInlineAsmConstraint(TRI, Constraint, VT); 953*81ad6265SDimitry Andric } 954*81ad6265SDimitry Andric 95504eeddc0SDimitry Andric static MachineBasicBlock * 95604eeddc0SDimitry Andric emitSelectPseudo(MachineInstr &MI, MachineBasicBlock *BB, unsigned Opcode) { 95704eeddc0SDimitry Andric 95804eeddc0SDimitry Andric const TargetInstrInfo &TII = *BB->getParent()->getSubtarget().getInstrInfo(); 95904eeddc0SDimitry Andric DebugLoc DL = MI.getDebugLoc(); 96004eeddc0SDimitry Andric 96104eeddc0SDimitry Andric // To "insert" a SELECT instruction, we actually have to insert the 96204eeddc0SDimitry Andric // diamond control-flow pattern. The incoming instruction knows the 96304eeddc0SDimitry Andric // destination vreg to set, the condition code register to branch on, the 96404eeddc0SDimitry Andric // true/false values to select between, and a branch opcode to use. 96504eeddc0SDimitry Andric const BasicBlock *LLVM_BB = BB->getBasicBlock(); 96604eeddc0SDimitry Andric MachineFunction::iterator It = ++BB->getIterator(); 96704eeddc0SDimitry Andric 96804eeddc0SDimitry Andric // thisMBB: 96904eeddc0SDimitry Andric // ... 97004eeddc0SDimitry Andric // TrueVal = ... 97104eeddc0SDimitry Andric // bt32 c, sinkMBB 97204eeddc0SDimitry Andric // fallthrough --> copyMBB 97304eeddc0SDimitry Andric MachineBasicBlock *thisMBB = BB; 97404eeddc0SDimitry Andric MachineFunction *F = BB->getParent(); 97504eeddc0SDimitry Andric MachineBasicBlock *copyMBB = F->CreateMachineBasicBlock(LLVM_BB); 97604eeddc0SDimitry Andric MachineBasicBlock *sinkMBB = F->CreateMachineBasicBlock(LLVM_BB); 97704eeddc0SDimitry Andric F->insert(It, copyMBB); 97804eeddc0SDimitry Andric F->insert(It, sinkMBB); 97904eeddc0SDimitry Andric 98004eeddc0SDimitry Andric // Transfer the remainder of BB and its successor edges to sinkMBB. 98104eeddc0SDimitry Andric sinkMBB->splice(sinkMBB->begin(), BB, 98204eeddc0SDimitry Andric std::next(MachineBasicBlock::iterator(MI)), BB->end()); 98304eeddc0SDimitry Andric sinkMBB->transferSuccessorsAndUpdatePHIs(BB); 98404eeddc0SDimitry Andric 98504eeddc0SDimitry Andric // Next, add the true and fallthrough blocks as its successors. 98604eeddc0SDimitry Andric BB->addSuccessor(copyMBB); 98704eeddc0SDimitry Andric BB->addSuccessor(sinkMBB); 98804eeddc0SDimitry Andric 98904eeddc0SDimitry Andric // bt32 condition, sinkMBB 99004eeddc0SDimitry Andric BuildMI(BB, DL, TII.get(Opcode)) 99104eeddc0SDimitry Andric .addReg(MI.getOperand(1).getReg()) 99204eeddc0SDimitry Andric .addMBB(sinkMBB); 99304eeddc0SDimitry Andric 99404eeddc0SDimitry Andric // copyMBB: 99504eeddc0SDimitry Andric // %FalseValue = ... 99604eeddc0SDimitry Andric // # fallthrough to sinkMBB 99704eeddc0SDimitry Andric BB = copyMBB; 99804eeddc0SDimitry Andric 99904eeddc0SDimitry Andric // Update machine-CFG edges 100004eeddc0SDimitry Andric BB->addSuccessor(sinkMBB); 100104eeddc0SDimitry Andric 100204eeddc0SDimitry Andric // sinkMBB: 100304eeddc0SDimitry Andric // %Result = phi [ %TrueValue, thisMBB ], [ %FalseValue, copyMBB ] 100404eeddc0SDimitry Andric // ... 100504eeddc0SDimitry Andric BB = sinkMBB; 100604eeddc0SDimitry Andric 100704eeddc0SDimitry Andric BuildMI(*BB, BB->begin(), DL, TII.get(CSKY::PHI), MI.getOperand(0).getReg()) 100804eeddc0SDimitry Andric .addReg(MI.getOperand(2).getReg()) 100904eeddc0SDimitry Andric .addMBB(thisMBB) 101004eeddc0SDimitry Andric .addReg(MI.getOperand(3).getReg()) 101104eeddc0SDimitry Andric .addMBB(copyMBB); 101204eeddc0SDimitry Andric 101304eeddc0SDimitry Andric MI.eraseFromParent(); // The pseudo instruction is gone now. 101404eeddc0SDimitry Andric 101504eeddc0SDimitry Andric return BB; 101604eeddc0SDimitry Andric } 101704eeddc0SDimitry Andric 101804eeddc0SDimitry Andric MachineBasicBlock * 101904eeddc0SDimitry Andric CSKYTargetLowering::EmitInstrWithCustomInserter(MachineInstr &MI, 102004eeddc0SDimitry Andric MachineBasicBlock *BB) const { 102104eeddc0SDimitry Andric switch (MI.getOpcode()) { 102204eeddc0SDimitry Andric default: 102304eeddc0SDimitry Andric llvm_unreachable("Unexpected instr type to insert"); 1024*81ad6265SDimitry Andric case CSKY::FSELS: 1025*81ad6265SDimitry Andric case CSKY::FSELD: 1026*81ad6265SDimitry Andric if (Subtarget.hasE2()) 1027*81ad6265SDimitry Andric return emitSelectPseudo(MI, BB, CSKY::BT32); 1028*81ad6265SDimitry Andric else 1029*81ad6265SDimitry Andric return emitSelectPseudo(MI, BB, CSKY::BT16); 103004eeddc0SDimitry Andric case CSKY::ISEL32: 103104eeddc0SDimitry Andric return emitSelectPseudo(MI, BB, CSKY::BT32); 103204eeddc0SDimitry Andric case CSKY::ISEL16: 103304eeddc0SDimitry Andric return emitSelectPseudo(MI, BB, CSKY::BT16); 103404eeddc0SDimitry Andric } 103504eeddc0SDimitry Andric } 103604eeddc0SDimitry Andric 103704eeddc0SDimitry Andric SDValue CSKYTargetLowering::getTargetConstantPoolValue(ExternalSymbolSDNode *N, 103804eeddc0SDimitry Andric EVT Ty, 103904eeddc0SDimitry Andric SelectionDAG &DAG, 104004eeddc0SDimitry Andric unsigned Flags) const { 104104eeddc0SDimitry Andric CSKYConstantPoolValue *CPV = 104204eeddc0SDimitry Andric CSKYConstantPoolSymbol::Create(Type::getInt32Ty(*DAG.getContext()), 104304eeddc0SDimitry Andric N->getSymbol(), 0, getModifier(Flags)); 104404eeddc0SDimitry Andric 104504eeddc0SDimitry Andric return DAG.getTargetConstantPool(CPV, Ty); 104604eeddc0SDimitry Andric } 104704eeddc0SDimitry Andric 104804eeddc0SDimitry Andric SDValue CSKYTargetLowering::getTargetConstantPoolValue(JumpTableSDNode *N, 104904eeddc0SDimitry Andric EVT Ty, 105004eeddc0SDimitry Andric SelectionDAG &DAG, 105104eeddc0SDimitry Andric unsigned Flags) const { 105204eeddc0SDimitry Andric CSKYConstantPoolValue *CPV = 105304eeddc0SDimitry Andric CSKYConstantPoolJT::Create(Type::getInt32Ty(*DAG.getContext()), 105404eeddc0SDimitry Andric N->getIndex(), 0, getModifier(Flags)); 105504eeddc0SDimitry Andric return DAG.getTargetConstantPool(CPV, Ty); 105604eeddc0SDimitry Andric } 105704eeddc0SDimitry Andric 105804eeddc0SDimitry Andric SDValue CSKYTargetLowering::getTargetConstantPoolValue(BlockAddressSDNode *N, 105904eeddc0SDimitry Andric EVT Ty, 106004eeddc0SDimitry Andric SelectionDAG &DAG, 106104eeddc0SDimitry Andric unsigned Flags) const { 106204eeddc0SDimitry Andric CSKYConstantPoolValue *CPV = CSKYConstantPoolConstant::Create( 106304eeddc0SDimitry Andric N->getBlockAddress(), CSKYCP::CPBlockAddress, 0, getModifier(Flags), 106404eeddc0SDimitry Andric false); 106504eeddc0SDimitry Andric return DAG.getTargetConstantPool(CPV, Ty); 106604eeddc0SDimitry Andric } 106704eeddc0SDimitry Andric 106804eeddc0SDimitry Andric SDValue CSKYTargetLowering::getTargetNode(GlobalAddressSDNode *N, SDLoc DL, 106904eeddc0SDimitry Andric EVT Ty, SelectionDAG &DAG, 107004eeddc0SDimitry Andric unsigned Flags) const { 107104eeddc0SDimitry Andric return DAG.getTargetGlobalAddress(N->getGlobal(), DL, Ty, 0, Flags); 107204eeddc0SDimitry Andric } 107304eeddc0SDimitry Andric 107404eeddc0SDimitry Andric SDValue CSKYTargetLowering::getTargetNode(ExternalSymbolSDNode *N, SDLoc DL, 107504eeddc0SDimitry Andric EVT Ty, SelectionDAG &DAG, 107604eeddc0SDimitry Andric unsigned Flags) const { 107704eeddc0SDimitry Andric return DAG.getTargetExternalSymbol(N->getSymbol(), Ty, Flags); 107804eeddc0SDimitry Andric } 107904eeddc0SDimitry Andric 108004eeddc0SDimitry Andric SDValue CSKYTargetLowering::getTargetNode(JumpTableSDNode *N, SDLoc DL, EVT Ty, 108104eeddc0SDimitry Andric SelectionDAG &DAG, 108204eeddc0SDimitry Andric unsigned Flags) const { 108304eeddc0SDimitry Andric return DAG.getTargetJumpTable(N->getIndex(), Ty, Flags); 108404eeddc0SDimitry Andric } 108504eeddc0SDimitry Andric 108604eeddc0SDimitry Andric SDValue CSKYTargetLowering::getTargetNode(BlockAddressSDNode *N, SDLoc DL, 108704eeddc0SDimitry Andric EVT Ty, SelectionDAG &DAG, 108804eeddc0SDimitry Andric unsigned Flags) const { 108904eeddc0SDimitry Andric return DAG.getTargetBlockAddress(N->getBlockAddress(), Ty, N->getOffset(), 109004eeddc0SDimitry Andric Flags); 109104eeddc0SDimitry Andric } 109204eeddc0SDimitry Andric 1093349cc55cSDimitry Andric const char *CSKYTargetLowering::getTargetNodeName(unsigned Opcode) const { 1094349cc55cSDimitry Andric switch (Opcode) { 1095349cc55cSDimitry Andric default: 1096349cc55cSDimitry Andric llvm_unreachable("unknown CSKYISD node"); 1097349cc55cSDimitry Andric case CSKYISD::NIE: 1098349cc55cSDimitry Andric return "CSKYISD::NIE"; 1099349cc55cSDimitry Andric case CSKYISD::NIR: 1100349cc55cSDimitry Andric return "CSKYISD::NIR"; 1101349cc55cSDimitry Andric case CSKYISD::RET: 1102349cc55cSDimitry Andric return "CSKYISD::RET"; 110304eeddc0SDimitry Andric case CSKYISD::CALL: 110404eeddc0SDimitry Andric return "CSKYISD::CALL"; 110504eeddc0SDimitry Andric case CSKYISD::CALLReg: 110604eeddc0SDimitry Andric return "CSKYISD::CALLReg"; 110704eeddc0SDimitry Andric case CSKYISD::TAIL: 110804eeddc0SDimitry Andric return "CSKYISD::TAIL"; 110904eeddc0SDimitry Andric case CSKYISD::TAILReg: 111004eeddc0SDimitry Andric return "CSKYISD::TAILReg"; 111104eeddc0SDimitry Andric case CSKYISD::LOAD_ADDR: 111204eeddc0SDimitry Andric return "CSKYISD::LOAD_ADDR"; 1113349cc55cSDimitry Andric case CSKYISD::BITCAST_TO_LOHI: 1114349cc55cSDimitry Andric return "CSKYISD::BITCAST_TO_LOHI"; 111504eeddc0SDimitry Andric case CSKYISD::BITCAST_FROM_LOHI: 111604eeddc0SDimitry Andric return "CSKYISD::BITCAST_FROM_LOHI"; 1117349cc55cSDimitry Andric } 1118349cc55cSDimitry Andric } 111904eeddc0SDimitry Andric 112004eeddc0SDimitry Andric SDValue CSKYTargetLowering::LowerGlobalAddress(SDValue Op, 112104eeddc0SDimitry Andric SelectionDAG &DAG) const { 112204eeddc0SDimitry Andric SDLoc DL(Op); 112304eeddc0SDimitry Andric EVT Ty = Op.getValueType(); 112404eeddc0SDimitry Andric GlobalAddressSDNode *N = cast<GlobalAddressSDNode>(Op); 112504eeddc0SDimitry Andric int64_t Offset = N->getOffset(); 112604eeddc0SDimitry Andric 112704eeddc0SDimitry Andric const GlobalValue *GV = N->getGlobal(); 112804eeddc0SDimitry Andric bool IsLocal = getTargetMachine().shouldAssumeDSOLocal(*GV->getParent(), GV); 112904eeddc0SDimitry Andric SDValue Addr = getAddr<GlobalAddressSDNode, false>(N, DAG, IsLocal); 113004eeddc0SDimitry Andric 113104eeddc0SDimitry Andric // In order to maximise the opportunity for common subexpression elimination, 113204eeddc0SDimitry Andric // emit a separate ADD node for the global address offset instead of folding 113304eeddc0SDimitry Andric // it in the global address node. Later peephole optimisations may choose to 113404eeddc0SDimitry Andric // fold it back in when profitable. 113504eeddc0SDimitry Andric if (Offset != 0) 113604eeddc0SDimitry Andric return DAG.getNode(ISD::ADD, DL, Ty, Addr, 113704eeddc0SDimitry Andric DAG.getConstant(Offset, DL, MVT::i32)); 113804eeddc0SDimitry Andric return Addr; 113904eeddc0SDimitry Andric } 114004eeddc0SDimitry Andric 114104eeddc0SDimitry Andric SDValue CSKYTargetLowering::LowerExternalSymbol(SDValue Op, 114204eeddc0SDimitry Andric SelectionDAG &DAG) const { 114304eeddc0SDimitry Andric ExternalSymbolSDNode *N = cast<ExternalSymbolSDNode>(Op); 114404eeddc0SDimitry Andric 114504eeddc0SDimitry Andric return getAddr(N, DAG, false); 114604eeddc0SDimitry Andric } 114704eeddc0SDimitry Andric 114804eeddc0SDimitry Andric SDValue CSKYTargetLowering::LowerJumpTable(SDValue Op, 114904eeddc0SDimitry Andric SelectionDAG &DAG) const { 115004eeddc0SDimitry Andric JumpTableSDNode *N = cast<JumpTableSDNode>(Op); 115104eeddc0SDimitry Andric 115204eeddc0SDimitry Andric return getAddr<JumpTableSDNode, false>(N, DAG); 115304eeddc0SDimitry Andric } 115404eeddc0SDimitry Andric 115504eeddc0SDimitry Andric SDValue CSKYTargetLowering::LowerBlockAddress(SDValue Op, 115604eeddc0SDimitry Andric SelectionDAG &DAG) const { 115704eeddc0SDimitry Andric BlockAddressSDNode *N = cast<BlockAddressSDNode>(Op); 115804eeddc0SDimitry Andric 115904eeddc0SDimitry Andric return getAddr(N, DAG); 116004eeddc0SDimitry Andric } 116104eeddc0SDimitry Andric 116204eeddc0SDimitry Andric SDValue CSKYTargetLowering::LowerVASTART(SDValue Op, SelectionDAG &DAG) const { 116304eeddc0SDimitry Andric MachineFunction &MF = DAG.getMachineFunction(); 116404eeddc0SDimitry Andric CSKYMachineFunctionInfo *FuncInfo = MF.getInfo<CSKYMachineFunctionInfo>(); 116504eeddc0SDimitry Andric 116604eeddc0SDimitry Andric SDLoc DL(Op); 116704eeddc0SDimitry Andric SDValue FI = DAG.getFrameIndex(FuncInfo->getVarArgsFrameIndex(), 116804eeddc0SDimitry Andric getPointerTy(MF.getDataLayout())); 116904eeddc0SDimitry Andric 117004eeddc0SDimitry Andric // vastart just stores the address of the VarArgsFrameIndex slot into the 117104eeddc0SDimitry Andric // memory location argument. 117204eeddc0SDimitry Andric const Value *SV = cast<SrcValueSDNode>(Op.getOperand(2))->getValue(); 117304eeddc0SDimitry Andric return DAG.getStore(Op.getOperand(0), DL, FI, Op.getOperand(1), 117404eeddc0SDimitry Andric MachinePointerInfo(SV)); 117504eeddc0SDimitry Andric } 117604eeddc0SDimitry Andric 117704eeddc0SDimitry Andric SDValue CSKYTargetLowering::LowerFRAMEADDR(SDValue Op, 117804eeddc0SDimitry Andric SelectionDAG &DAG) const { 117904eeddc0SDimitry Andric const CSKYRegisterInfo &RI = *Subtarget.getRegisterInfo(); 118004eeddc0SDimitry Andric MachineFunction &MF = DAG.getMachineFunction(); 118104eeddc0SDimitry Andric MachineFrameInfo &MFI = MF.getFrameInfo(); 118204eeddc0SDimitry Andric MFI.setFrameAddressIsTaken(true); 118304eeddc0SDimitry Andric 118404eeddc0SDimitry Andric EVT VT = Op.getValueType(); 118504eeddc0SDimitry Andric SDLoc dl(Op); 118604eeddc0SDimitry Andric unsigned Depth = cast<ConstantSDNode>(Op.getOperand(0))->getZExtValue(); 118704eeddc0SDimitry Andric Register FrameReg = RI.getFrameRegister(MF); 118804eeddc0SDimitry Andric SDValue FrameAddr = DAG.getCopyFromReg(DAG.getEntryNode(), dl, FrameReg, VT); 118904eeddc0SDimitry Andric while (Depth--) 119004eeddc0SDimitry Andric FrameAddr = DAG.getLoad(VT, dl, DAG.getEntryNode(), FrameAddr, 119104eeddc0SDimitry Andric MachinePointerInfo()); 119204eeddc0SDimitry Andric return FrameAddr; 119304eeddc0SDimitry Andric } 119404eeddc0SDimitry Andric 119504eeddc0SDimitry Andric SDValue CSKYTargetLowering::LowerRETURNADDR(SDValue Op, 119604eeddc0SDimitry Andric SelectionDAG &DAG) const { 119704eeddc0SDimitry Andric const CSKYRegisterInfo &RI = *Subtarget.getRegisterInfo(); 119804eeddc0SDimitry Andric MachineFunction &MF = DAG.getMachineFunction(); 119904eeddc0SDimitry Andric MachineFrameInfo &MFI = MF.getFrameInfo(); 120004eeddc0SDimitry Andric MFI.setReturnAddressIsTaken(true); 120104eeddc0SDimitry Andric 120204eeddc0SDimitry Andric if (verifyReturnAddressArgumentIsConstant(Op, DAG)) 120304eeddc0SDimitry Andric return SDValue(); 120404eeddc0SDimitry Andric 120504eeddc0SDimitry Andric EVT VT = Op.getValueType(); 120604eeddc0SDimitry Andric SDLoc dl(Op); 120704eeddc0SDimitry Andric unsigned Depth = cast<ConstantSDNode>(Op.getOperand(0))->getZExtValue(); 120804eeddc0SDimitry Andric if (Depth) { 120904eeddc0SDimitry Andric SDValue FrameAddr = LowerFRAMEADDR(Op, DAG); 121004eeddc0SDimitry Andric SDValue Offset = DAG.getConstant(4, dl, MVT::i32); 121104eeddc0SDimitry Andric return DAG.getLoad(VT, dl, DAG.getEntryNode(), 121204eeddc0SDimitry Andric DAG.getNode(ISD::ADD, dl, VT, FrameAddr, Offset), 121304eeddc0SDimitry Andric MachinePointerInfo()); 121404eeddc0SDimitry Andric } 121504eeddc0SDimitry Andric // Return the value of the return address register, marking it an implicit 121604eeddc0SDimitry Andric // live-in. 121704eeddc0SDimitry Andric unsigned Reg = MF.addLiveIn(RI.getRARegister(), getRegClassFor(MVT::i32)); 121804eeddc0SDimitry Andric return DAG.getCopyFromReg(DAG.getEntryNode(), dl, Reg, VT); 121904eeddc0SDimitry Andric } 122004eeddc0SDimitry Andric 122104eeddc0SDimitry Andric Register CSKYTargetLowering::getExceptionPointerRegister( 122204eeddc0SDimitry Andric const Constant *PersonalityFn) const { 122304eeddc0SDimitry Andric return CSKY::R0; 122404eeddc0SDimitry Andric } 122504eeddc0SDimitry Andric 122604eeddc0SDimitry Andric Register CSKYTargetLowering::getExceptionSelectorRegister( 122704eeddc0SDimitry Andric const Constant *PersonalityFn) const { 122804eeddc0SDimitry Andric return CSKY::R1; 122904eeddc0SDimitry Andric } 123004eeddc0SDimitry Andric 123104eeddc0SDimitry Andric SDValue CSKYTargetLowering::LowerGlobalTLSAddress(SDValue Op, 123204eeddc0SDimitry Andric SelectionDAG &DAG) const { 123304eeddc0SDimitry Andric SDLoc DL(Op); 123404eeddc0SDimitry Andric EVT Ty = Op.getValueType(); 123504eeddc0SDimitry Andric GlobalAddressSDNode *N = cast<GlobalAddressSDNode>(Op); 123604eeddc0SDimitry Andric int64_t Offset = N->getOffset(); 123704eeddc0SDimitry Andric MVT XLenVT = MVT::i32; 123804eeddc0SDimitry Andric 123904eeddc0SDimitry Andric TLSModel::Model Model = getTargetMachine().getTLSModel(N->getGlobal()); 124004eeddc0SDimitry Andric SDValue Addr; 124104eeddc0SDimitry Andric switch (Model) { 124204eeddc0SDimitry Andric case TLSModel::LocalExec: 124304eeddc0SDimitry Andric Addr = getStaticTLSAddr(N, DAG, /*UseGOT=*/false); 124404eeddc0SDimitry Andric break; 124504eeddc0SDimitry Andric case TLSModel::InitialExec: 124604eeddc0SDimitry Andric Addr = getStaticTLSAddr(N, DAG, /*UseGOT=*/true); 124704eeddc0SDimitry Andric break; 124804eeddc0SDimitry Andric case TLSModel::LocalDynamic: 124904eeddc0SDimitry Andric case TLSModel::GeneralDynamic: 125004eeddc0SDimitry Andric Addr = getDynamicTLSAddr(N, DAG); 125104eeddc0SDimitry Andric break; 125204eeddc0SDimitry Andric } 125304eeddc0SDimitry Andric 125404eeddc0SDimitry Andric // In order to maximise the opportunity for common subexpression elimination, 125504eeddc0SDimitry Andric // emit a separate ADD node for the global address offset instead of folding 125604eeddc0SDimitry Andric // it in the global address node. Later peephole optimisations may choose to 125704eeddc0SDimitry Andric // fold it back in when profitable. 125804eeddc0SDimitry Andric if (Offset != 0) 125904eeddc0SDimitry Andric return DAG.getNode(ISD::ADD, DL, Ty, Addr, 126004eeddc0SDimitry Andric DAG.getConstant(Offset, DL, XLenVT)); 126104eeddc0SDimitry Andric return Addr; 126204eeddc0SDimitry Andric } 126304eeddc0SDimitry Andric 126404eeddc0SDimitry Andric SDValue CSKYTargetLowering::getStaticTLSAddr(GlobalAddressSDNode *N, 126504eeddc0SDimitry Andric SelectionDAG &DAG, 126604eeddc0SDimitry Andric bool UseGOT) const { 126704eeddc0SDimitry Andric MachineFunction &MF = DAG.getMachineFunction(); 126804eeddc0SDimitry Andric CSKYMachineFunctionInfo *CFI = MF.getInfo<CSKYMachineFunctionInfo>(); 126904eeddc0SDimitry Andric 127004eeddc0SDimitry Andric unsigned CSKYPCLabelIndex = CFI->createPICLabelUId(); 127104eeddc0SDimitry Andric 127204eeddc0SDimitry Andric SDLoc DL(N); 127304eeddc0SDimitry Andric EVT Ty = getPointerTy(DAG.getDataLayout()); 127404eeddc0SDimitry Andric 127504eeddc0SDimitry Andric CSKYCP::CSKYCPModifier Flag = UseGOT ? CSKYCP::TLSIE : CSKYCP::TLSLE; 127604eeddc0SDimitry Andric bool AddCurrentAddr = UseGOT ? true : false; 127704eeddc0SDimitry Andric unsigned char PCAjust = UseGOT ? 4 : 0; 127804eeddc0SDimitry Andric 127904eeddc0SDimitry Andric CSKYConstantPoolValue *CPV = 128004eeddc0SDimitry Andric CSKYConstantPoolConstant::Create(N->getGlobal(), CSKYCP::CPValue, PCAjust, 128104eeddc0SDimitry Andric Flag, AddCurrentAddr, CSKYPCLabelIndex); 128204eeddc0SDimitry Andric SDValue CAddr = DAG.getTargetConstantPool(CPV, Ty); 128304eeddc0SDimitry Andric 128404eeddc0SDimitry Andric SDValue Load; 128504eeddc0SDimitry Andric if (UseGOT) { 128604eeddc0SDimitry Andric SDValue PICLabel = DAG.getTargetConstant(CSKYPCLabelIndex, DL, MVT::i32); 128704eeddc0SDimitry Andric auto *LRWGRS = DAG.getMachineNode(CSKY::PseudoTLSLA32, DL, {Ty, Ty}, 128804eeddc0SDimitry Andric {CAddr, PICLabel}); 128904eeddc0SDimitry Andric auto LRWADDGRS = 129004eeddc0SDimitry Andric DAG.getNode(ISD::ADD, DL, Ty, SDValue(LRWGRS, 0), SDValue(LRWGRS, 1)); 129104eeddc0SDimitry Andric Load = DAG.getLoad(Ty, DL, DAG.getEntryNode(), LRWADDGRS, 129204eeddc0SDimitry Andric MachinePointerInfo(N->getGlobal())); 129304eeddc0SDimitry Andric } else { 129404eeddc0SDimitry Andric Load = SDValue(DAG.getMachineNode(CSKY::LRW32, DL, Ty, CAddr), 0); 129504eeddc0SDimitry Andric } 129604eeddc0SDimitry Andric 129704eeddc0SDimitry Andric // Add the thread pointer. 129804eeddc0SDimitry Andric SDValue TPReg = DAG.getRegister(CSKY::R31, MVT::i32); 129904eeddc0SDimitry Andric return DAG.getNode(ISD::ADD, DL, Ty, Load, TPReg); 130004eeddc0SDimitry Andric } 130104eeddc0SDimitry Andric 130204eeddc0SDimitry Andric SDValue CSKYTargetLowering::getDynamicTLSAddr(GlobalAddressSDNode *N, 130304eeddc0SDimitry Andric SelectionDAG &DAG) const { 130404eeddc0SDimitry Andric MachineFunction &MF = DAG.getMachineFunction(); 130504eeddc0SDimitry Andric CSKYMachineFunctionInfo *CFI = MF.getInfo<CSKYMachineFunctionInfo>(); 130604eeddc0SDimitry Andric 130704eeddc0SDimitry Andric unsigned CSKYPCLabelIndex = CFI->createPICLabelUId(); 130804eeddc0SDimitry Andric 130904eeddc0SDimitry Andric SDLoc DL(N); 131004eeddc0SDimitry Andric EVT Ty = getPointerTy(DAG.getDataLayout()); 131104eeddc0SDimitry Andric IntegerType *CallTy = Type::getIntNTy(*DAG.getContext(), Ty.getSizeInBits()); 131204eeddc0SDimitry Andric 131304eeddc0SDimitry Andric CSKYConstantPoolValue *CPV = 131404eeddc0SDimitry Andric CSKYConstantPoolConstant::Create(N->getGlobal(), CSKYCP::CPValue, 4, 131504eeddc0SDimitry Andric CSKYCP::TLSGD, true, CSKYPCLabelIndex); 131604eeddc0SDimitry Andric SDValue Addr = DAG.getTargetConstantPool(CPV, Ty); 131704eeddc0SDimitry Andric SDValue PICLabel = DAG.getTargetConstant(CSKYPCLabelIndex, DL, MVT::i32); 131804eeddc0SDimitry Andric 131904eeddc0SDimitry Andric auto *LRWGRS = 132004eeddc0SDimitry Andric DAG.getMachineNode(CSKY::PseudoTLSLA32, DL, {Ty, Ty}, {Addr, PICLabel}); 132104eeddc0SDimitry Andric 132204eeddc0SDimitry Andric auto Load = 132304eeddc0SDimitry Andric DAG.getNode(ISD::ADD, DL, Ty, SDValue(LRWGRS, 0), SDValue(LRWGRS, 1)); 132404eeddc0SDimitry Andric 132504eeddc0SDimitry Andric // Prepare argument list to generate call. 132604eeddc0SDimitry Andric ArgListTy Args; 132704eeddc0SDimitry Andric ArgListEntry Entry; 132804eeddc0SDimitry Andric Entry.Node = Load; 132904eeddc0SDimitry Andric Entry.Ty = CallTy; 133004eeddc0SDimitry Andric Args.push_back(Entry); 133104eeddc0SDimitry Andric 133204eeddc0SDimitry Andric // Setup call to __tls_get_addr. 133304eeddc0SDimitry Andric TargetLowering::CallLoweringInfo CLI(DAG); 133404eeddc0SDimitry Andric CLI.setDebugLoc(DL) 133504eeddc0SDimitry Andric .setChain(DAG.getEntryNode()) 133604eeddc0SDimitry Andric .setLibCallee(CallingConv::C, CallTy, 133704eeddc0SDimitry Andric DAG.getExternalSymbol("__tls_get_addr", Ty), 133804eeddc0SDimitry Andric std::move(Args)); 133904eeddc0SDimitry Andric SDValue V = LowerCallTo(CLI).first; 134004eeddc0SDimitry Andric 134104eeddc0SDimitry Andric return V; 134204eeddc0SDimitry Andric } 1343