xref: /freebsd-src/contrib/llvm-project/llvm/lib/Target/CSKY/CSKYISelLowering.cpp (revision 81ad626541db97eb356e2c1d4a20eb2a26a766ab)
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