xref: /llvm-project/llvm/lib/Target/CSKY/CSKYISelLowering.cpp (revision 754ed95b6672b9a678a994cc652862a91cdc4406)
1cf78715cSZi Xuan Wu //===-- CSKYISelLowering.cpp - CSKY DAG Lowering Implementation  ----------===//
2cf78715cSZi Xuan Wu //
3cf78715cSZi Xuan Wu // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4cf78715cSZi Xuan Wu // See https://llvm.org/LICENSE.txt for license information.
5cf78715cSZi Xuan Wu // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6cf78715cSZi Xuan Wu //
7cf78715cSZi Xuan Wu //===----------------------------------------------------------------------===//
8cf78715cSZi Xuan Wu //
9cf78715cSZi Xuan Wu // This file defines the interfaces that CSKY uses to lower LLVM code into a
10cf78715cSZi Xuan Wu // selection DAG.
11cf78715cSZi Xuan Wu //
12cf78715cSZi Xuan Wu //===----------------------------------------------------------------------===//
13cf78715cSZi Xuan Wu 
14cf78715cSZi Xuan Wu #include "CSKYISelLowering.h"
15cf78715cSZi Xuan Wu #include "CSKYCallingConv.h"
168ddc8169SZi Xuan Wu #include "CSKYConstantPoolValue.h"
17cf78715cSZi Xuan Wu #include "CSKYMachineFunctionInfo.h"
18cf78715cSZi Xuan Wu #include "CSKYRegisterInfo.h"
19cf78715cSZi Xuan Wu #include "CSKYSubtarget.h"
20cf78715cSZi Xuan Wu #include "llvm/ADT/Statistic.h"
21cf78715cSZi Xuan Wu #include "llvm/CodeGen/CallingConvLower.h"
22989f1c72Sserge-sans-paille #include "llvm/CodeGen/MachineFrameInfo.h"
23cf78715cSZi Xuan Wu #include "llvm/CodeGen/MachineJumpTableInfo.h"
24cf78715cSZi Xuan Wu #include "llvm/Support/Debug.h"
25cf78715cSZi Xuan Wu 
26cf78715cSZi Xuan Wu using namespace llvm;
27cf78715cSZi Xuan Wu 
28cf78715cSZi Xuan Wu #define DEBUG_TYPE "csky-isel-lowering"
29cf78715cSZi Xuan Wu 
30cf78715cSZi Xuan Wu STATISTIC(NumTailCalls, "Number of tail calls");
31cf78715cSZi Xuan Wu 
32cf78715cSZi Xuan Wu #include "CSKYGenCallingConv.inc"
33cf78715cSZi Xuan Wu 
34cf78715cSZi Xuan Wu static const MCPhysReg GPRArgRegs[] = {CSKY::R0, CSKY::R1, CSKY::R2, CSKY::R3};
35cf78715cSZi Xuan Wu 
36cf78715cSZi Xuan Wu CSKYTargetLowering::CSKYTargetLowering(const TargetMachine &TM,
37cf78715cSZi Xuan Wu                                        const CSKYSubtarget &STI)
38cf78715cSZi Xuan Wu     : TargetLowering(TM), Subtarget(STI) {
39cf78715cSZi Xuan Wu   // Register Class
40cf78715cSZi Xuan Wu   addRegisterClass(MVT::i32, &CSKY::GPRRegClass);
41cf78715cSZi Xuan Wu 
424ad517e6SZi Xuan Wu   if (STI.useHardFloat()) {
434ad517e6SZi Xuan Wu     if (STI.hasFPUv2SingleFloat())
444ad517e6SZi Xuan Wu       addRegisterClass(MVT::f32, &CSKY::sFPR32RegClass);
454ad517e6SZi Xuan Wu     else if (STI.hasFPUv3SingleFloat())
464ad517e6SZi Xuan Wu       addRegisterClass(MVT::f32, &CSKY::FPR32RegClass);
474ad517e6SZi Xuan Wu 
484ad517e6SZi Xuan Wu     if (STI.hasFPUv2DoubleFloat())
494ad517e6SZi Xuan Wu       addRegisterClass(MVT::f64, &CSKY::sFPR64RegClass);
504ad517e6SZi Xuan Wu     else if (STI.hasFPUv3DoubleFloat())
514ad517e6SZi Xuan Wu       addRegisterClass(MVT::f64, &CSKY::FPR64RegClass);
524ad517e6SZi Xuan Wu   }
534ad517e6SZi Xuan Wu 
54e744e51bSSergei Barannikov   setOperationAction(ISD::UADDO_CARRY, MVT::i32, Legal);
55e744e51bSSergei Barannikov   setOperationAction(ISD::USUBO_CARRY, MVT::i32, Legal);
56a556ec88SZi Xuan Wu   setOperationAction(ISD::BITREVERSE, MVT::i32, Legal);
57a556ec88SZi Xuan Wu 
58a556ec88SZi Xuan Wu   setOperationAction(ISD::SREM, MVT::i32, Expand);
59a556ec88SZi Xuan Wu   setOperationAction(ISD::UREM, MVT::i32, Expand);
60a556ec88SZi Xuan Wu   setOperationAction(ISD::UDIVREM, MVT::i32, Expand);
61a556ec88SZi Xuan Wu   setOperationAction(ISD::SDIVREM, MVT::i32, Expand);
62a556ec88SZi Xuan Wu   setOperationAction(ISD::CTPOP, MVT::i32, Expand);
63a556ec88SZi Xuan Wu   setOperationAction(ISD::ROTR, MVT::i32, Expand);
64a556ec88SZi Xuan Wu   setOperationAction(ISD::SHL_PARTS, MVT::i32, Expand);
65a556ec88SZi Xuan Wu   setOperationAction(ISD::SRL_PARTS, MVT::i32, Expand);
66a556ec88SZi Xuan Wu   setOperationAction(ISD::SRA_PARTS, MVT::i32, Expand);
67a556ec88SZi Xuan Wu   setOperationAction(ISD::UMUL_LOHI, MVT::i32, Expand);
68a556ec88SZi Xuan Wu   setOperationAction(ISD::SMUL_LOHI, MVT::i32, Expand);
699566cf16SZi Xuan Wu   setOperationAction(ISD::SELECT_CC, MVT::i32, Expand);
709566cf16SZi Xuan Wu   setOperationAction(ISD::BR_CC, MVT::i32, Expand);
719566cf16SZi Xuan Wu   setOperationAction(ISD::BR_JT, MVT::Other, Expand);
72a556ec88SZi Xuan Wu   setOperationAction(ISD::DYNAMIC_STACKALLOC, MVT::i32, Expand);
73a556ec88SZi Xuan Wu   setOperationAction(ISD::STACKSAVE, MVT::Other, Expand);
74a556ec88SZi Xuan Wu   setOperationAction(ISD::STACKRESTORE, MVT::Other, Expand);
75a556ec88SZi Xuan Wu   setOperationAction(ISD::MULHS, MVT::i32, Expand);
76a556ec88SZi Xuan Wu   setOperationAction(ISD::MULHU, MVT::i32, Expand);
778ddc8169SZi Xuan Wu   setOperationAction(ISD::VAARG, MVT::Other, Expand);
788ddc8169SZi Xuan Wu   setOperationAction(ISD::VACOPY, MVT::Other, Expand);
798ddc8169SZi Xuan Wu   setOperationAction(ISD::VAEND, MVT::Other, Expand);
808ddc8169SZi Xuan Wu 
818ddc8169SZi Xuan Wu   setLoadExtAction(ISD::EXTLOAD, MVT::i32, MVT::i1, Promote);
828ddc8169SZi Xuan Wu   setLoadExtAction(ISD::SEXTLOAD, MVT::i32, MVT::i1, Promote);
838ddc8169SZi Xuan Wu   setLoadExtAction(ISD::ZEXTLOAD, MVT::i32, MVT::i1, Promote);
848ddc8169SZi Xuan Wu 
858ddc8169SZi Xuan Wu   setOperationAction(ISD::GlobalAddress, MVT::i32, Custom);
868ddc8169SZi Xuan Wu   setOperationAction(ISD::ExternalSymbol, MVT::i32, Custom);
878ddc8169SZi Xuan Wu   setOperationAction(ISD::GlobalTLSAddress, MVT::i32, Custom);
888ddc8169SZi Xuan Wu   setOperationAction(ISD::BlockAddress, MVT::i32, Custom);
89f4d61cdfSZi Xuan Wu (Zeson)   if (!Subtarget.hasE2()) {
90f4d61cdfSZi Xuan Wu (Zeson)     setOperationAction(ISD::ConstantPool, MVT::i32, Custom);
91f4d61cdfSZi Xuan Wu (Zeson)   }
928ddc8169SZi Xuan Wu   setOperationAction(ISD::JumpTable, MVT::i32, Custom);
938ddc8169SZi Xuan Wu   setOperationAction(ISD::VASTART, MVT::Other, Custom);
948ddc8169SZi Xuan Wu 
958ddc8169SZi Xuan Wu   if (!Subtarget.hasE2()) {
968ddc8169SZi Xuan Wu     setLoadExtAction(ISD::SEXTLOAD, MVT::i32, MVT::i8, Expand);
978ddc8169SZi Xuan Wu     setLoadExtAction(ISD::SEXTLOAD, MVT::i32, MVT::i16, Expand);
988ddc8169SZi Xuan Wu     setOperationAction(ISD::CTLZ, MVT::i32, Expand);
998ddc8169SZi Xuan Wu     setOperationAction(ISD::BSWAP, MVT::i32, Expand);
1008ddc8169SZi Xuan Wu   }
1018ddc8169SZi Xuan Wu 
1028ddc8169SZi Xuan Wu   if (!Subtarget.has2E3()) {
1038ddc8169SZi Xuan Wu     setOperationAction(ISD::ABS, MVT::i32, Expand);
1048ddc8169SZi Xuan Wu     setOperationAction(ISD::BITREVERSE, MVT::i32, Expand);
10580cd5059SBen Shi     setOperationAction(ISD::CTTZ, MVT::i32, Expand);
1068ddc8169SZi Xuan Wu     setOperationAction(ISD::SDIV, MVT::i32, Expand);
1078ddc8169SZi Xuan Wu     setOperationAction(ISD::UDIV, MVT::i32, Expand);
1088ddc8169SZi Xuan Wu   }
1098ddc8169SZi Xuan Wu 
1108ddc8169SZi Xuan Wu   setOperationAction(ISD::ATOMIC_FENCE, MVT::Other, Expand);
1118ddc8169SZi Xuan Wu 
1124ad517e6SZi Xuan Wu   // Float
1134ad517e6SZi Xuan Wu 
1144ad517e6SZi Xuan Wu   ISD::CondCode FPCCToExtend[] = {
1154ad517e6SZi Xuan Wu       ISD::SETONE, ISD::SETUEQ, ISD::SETUGT,
1164ad517e6SZi Xuan Wu       ISD::SETUGE, ISD::SETULT, ISD::SETULE,
1174ad517e6SZi Xuan Wu   };
1184ad517e6SZi Xuan Wu 
11956e33d98SBen Shi   ISD::NodeType FPOpToExpand[] = {
12056e33d98SBen Shi       ISD::FSIN, ISD::FCOS,      ISD::FSINCOS,    ISD::FPOW,
12156e33d98SBen Shi       ISD::FREM, ISD::FCOPYSIGN, ISD::FP16_TO_FP, ISD::FP_TO_FP16};
1224ad517e6SZi Xuan Wu 
1234ad517e6SZi Xuan Wu   if (STI.useHardFloat()) {
1244ad517e6SZi Xuan Wu 
1254ad517e6SZi Xuan Wu     MVT AllVTy[] = {MVT::f32, MVT::f64};
1264ad517e6SZi Xuan Wu 
1274ad517e6SZi Xuan Wu     for (auto VT : AllVTy) {
1284ad517e6SZi Xuan Wu       setOperationAction(ISD::FREM, VT, Expand);
1294ad517e6SZi Xuan Wu       setOperationAction(ISD::SELECT_CC, VT, Expand);
1304ad517e6SZi Xuan Wu       setOperationAction(ISD::BR_CC, VT, Expand);
1314ad517e6SZi Xuan Wu 
1324ad517e6SZi Xuan Wu       for (auto CC : FPCCToExtend)
1334ad517e6SZi Xuan Wu         setCondCodeAction(CC, VT, Expand);
1344ad517e6SZi Xuan Wu       for (auto Op : FPOpToExpand)
1354ad517e6SZi Xuan Wu         setOperationAction(Op, VT, Expand);
1364ad517e6SZi Xuan Wu     }
1374ad517e6SZi Xuan Wu 
1384ad517e6SZi Xuan Wu     if (STI.hasFPUv2SingleFloat() || STI.hasFPUv3SingleFloat()) {
1394ad517e6SZi Xuan Wu       setOperationAction(ISD::ConstantFP, MVT::f32, Legal);
140d90468d1SZi Xuan Wu (Zeson)       setLoadExtAction(ISD::EXTLOAD, MVT::f32, MVT::f16, Expand);
141d90468d1SZi Xuan Wu (Zeson)       setTruncStoreAction(MVT::f32, MVT::f16, Expand);
1424ad517e6SZi Xuan Wu     }
1434ad517e6SZi Xuan Wu     if (STI.hasFPUv2DoubleFloat() || STI.hasFPUv3DoubleFloat()) {
1444ad517e6SZi Xuan Wu       setLoadExtAction(ISD::EXTLOAD, MVT::f64, MVT::f32, Expand);
1454ad517e6SZi Xuan Wu       setTruncStoreAction(MVT::f64, MVT::f32, Expand);
146d90468d1SZi Xuan Wu (Zeson)       setLoadExtAction(ISD::EXTLOAD, MVT::f64, MVT::f16, Expand);
147d90468d1SZi Xuan Wu (Zeson)       setTruncStoreAction(MVT::f64, MVT::f16, Expand);
1484ad517e6SZi Xuan Wu     }
1494ad517e6SZi Xuan Wu   }
1504ad517e6SZi Xuan Wu 
151cf78715cSZi Xuan Wu   // Compute derived properties from the register classes.
152cf78715cSZi Xuan Wu   computeRegisterProperties(STI.getRegisterInfo());
153cf78715cSZi Xuan Wu 
154cf78715cSZi Xuan Wu   setBooleanContents(UndefinedBooleanContent);
155cf78715cSZi Xuan Wu   setBooleanVectorContents(ZeroOrNegativeOneBooleanContent);
156cf78715cSZi Xuan Wu 
157cf78715cSZi Xuan Wu   // TODO: Add atomic support fully.
158cf78715cSZi Xuan Wu   setMaxAtomicSizeInBitsSupported(0);
159cf78715cSZi Xuan Wu 
160cf78715cSZi Xuan Wu   setStackPointerRegisterToSaveRestore(CSKY::R14);
16180eacb1bSGuillaume Chatelet   setMinFunctionAlignment(Align(2));
162cf78715cSZi Xuan Wu   setSchedulingPreference(Sched::Source);
163cf78715cSZi Xuan Wu }
164cf78715cSZi Xuan Wu 
1658ddc8169SZi Xuan Wu SDValue CSKYTargetLowering::LowerOperation(SDValue Op,
1668ddc8169SZi Xuan Wu                                            SelectionDAG &DAG) const {
1678ddc8169SZi Xuan Wu   switch (Op.getOpcode()) {
1688ddc8169SZi Xuan Wu   default:
1698ddc8169SZi Xuan Wu     llvm_unreachable("unimplemented op");
1708ddc8169SZi Xuan Wu   case ISD::GlobalAddress:
1718ddc8169SZi Xuan Wu     return LowerGlobalAddress(Op, DAG);
1728ddc8169SZi Xuan Wu   case ISD::ExternalSymbol:
1738ddc8169SZi Xuan Wu     return LowerExternalSymbol(Op, DAG);
17482bb8a58SZi Xuan Wu   case ISD::GlobalTLSAddress:
17582bb8a58SZi Xuan Wu     return LowerGlobalTLSAddress(Op, DAG);
1768ddc8169SZi Xuan Wu   case ISD::JumpTable:
1778ddc8169SZi Xuan Wu     return LowerJumpTable(Op, DAG);
1788ddc8169SZi Xuan Wu   case ISD::BlockAddress:
1798ddc8169SZi Xuan Wu     return LowerBlockAddress(Op, DAG);
180f4d61cdfSZi Xuan Wu (Zeson)   case ISD::ConstantPool:
181f4d61cdfSZi Xuan Wu (Zeson)     return LowerConstantPool(Op, DAG);
1828ddc8169SZi Xuan Wu   case ISD::VASTART:
1838ddc8169SZi Xuan Wu     return LowerVASTART(Op, DAG);
1848ddc8169SZi Xuan Wu   case ISD::FRAMEADDR:
1858ddc8169SZi Xuan Wu     return LowerFRAMEADDR(Op, DAG);
1868ddc8169SZi Xuan Wu   case ISD::RETURNADDR:
1878ddc8169SZi Xuan Wu     return LowerRETURNADDR(Op, DAG);
1888ddc8169SZi Xuan Wu   }
1898ddc8169SZi Xuan Wu }
1908ddc8169SZi Xuan Wu 
191cf78715cSZi Xuan Wu EVT CSKYTargetLowering::getSetCCResultType(const DataLayout &DL,
192cf78715cSZi Xuan Wu                                            LLVMContext &Context, EVT VT) const {
193cf78715cSZi Xuan Wu   if (!VT.isVector())
194cf78715cSZi Xuan Wu     return MVT::i32;
195cf78715cSZi Xuan Wu 
196cf78715cSZi Xuan Wu   return VT.changeVectorElementTypeToInteger();
197cf78715cSZi Xuan Wu }
198cf78715cSZi Xuan Wu 
199cf78715cSZi Xuan Wu static SDValue convertValVTToLocVT(SelectionDAG &DAG, SDValue Val,
200cf78715cSZi Xuan Wu                                    const CCValAssign &VA, const SDLoc &DL) {
201cf78715cSZi Xuan Wu   EVT LocVT = VA.getLocVT();
202cf78715cSZi Xuan Wu 
203cf78715cSZi Xuan Wu   switch (VA.getLocInfo()) {
204cf78715cSZi Xuan Wu   default:
205cf78715cSZi Xuan Wu     llvm_unreachable("Unexpected CCValAssign::LocInfo");
206cf78715cSZi Xuan Wu   case CCValAssign::Full:
207cf78715cSZi Xuan Wu     break;
208cf78715cSZi Xuan Wu   case CCValAssign::BCvt:
209cf78715cSZi Xuan Wu     Val = DAG.getNode(ISD::BITCAST, DL, LocVT, Val);
210cf78715cSZi Xuan Wu     break;
211cf78715cSZi Xuan Wu   }
212cf78715cSZi Xuan Wu   return Val;
213cf78715cSZi Xuan Wu }
214cf78715cSZi Xuan Wu 
215cf78715cSZi Xuan Wu static SDValue convertLocVTToValVT(SelectionDAG &DAG, SDValue Val,
216cf78715cSZi Xuan Wu                                    const CCValAssign &VA, const SDLoc &DL) {
217cf78715cSZi Xuan Wu   switch (VA.getLocInfo()) {
218cf78715cSZi Xuan Wu   default:
219cf78715cSZi Xuan Wu     llvm_unreachable("Unexpected CCValAssign::LocInfo");
220cf78715cSZi Xuan Wu   case CCValAssign::Full:
221cf78715cSZi Xuan Wu     break;
222cf78715cSZi Xuan Wu   case CCValAssign::BCvt:
223cf78715cSZi Xuan Wu     Val = DAG.getNode(ISD::BITCAST, DL, VA.getValVT(), Val);
224cf78715cSZi Xuan Wu     break;
225cf78715cSZi Xuan Wu   }
226cf78715cSZi Xuan Wu   return Val;
227cf78715cSZi Xuan Wu }
228cf78715cSZi Xuan Wu 
229cf78715cSZi Xuan Wu static SDValue unpackFromRegLoc(const CSKYSubtarget &Subtarget,
230cf78715cSZi Xuan Wu                                 SelectionDAG &DAG, SDValue Chain,
231cf78715cSZi Xuan Wu                                 const CCValAssign &VA, const SDLoc &DL) {
232cf78715cSZi Xuan Wu   MachineFunction &MF = DAG.getMachineFunction();
233cf78715cSZi Xuan Wu   MachineRegisterInfo &RegInfo = MF.getRegInfo();
234cf78715cSZi Xuan Wu   EVT LocVT = VA.getLocVT();
235cf78715cSZi Xuan Wu   SDValue Val;
236cf78715cSZi Xuan Wu   const TargetRegisterClass *RC;
237cf78715cSZi Xuan Wu 
238cf78715cSZi Xuan Wu   switch (LocVT.getSimpleVT().SimpleTy) {
239cf78715cSZi Xuan Wu   default:
240cf78715cSZi Xuan Wu     llvm_unreachable("Unexpected register type");
241cf78715cSZi Xuan Wu   case MVT::i32:
242cf78715cSZi Xuan Wu     RC = &CSKY::GPRRegClass;
243cf78715cSZi Xuan Wu     break;
2448ddc8169SZi Xuan Wu   case MVT::f32:
2458ddc8169SZi Xuan Wu     RC = Subtarget.hasFPUv2SingleFloat() ? &CSKY::sFPR32RegClass
2468ddc8169SZi Xuan Wu                                          : &CSKY::FPR32RegClass;
2478ddc8169SZi Xuan Wu     break;
2488ddc8169SZi Xuan Wu   case MVT::f64:
2498ddc8169SZi Xuan Wu     RC = Subtarget.hasFPUv2DoubleFloat() ? &CSKY::sFPR64RegClass
2508ddc8169SZi Xuan Wu                                          : &CSKY::FPR64RegClass;
2518ddc8169SZi Xuan Wu     break;
252cf78715cSZi Xuan Wu   }
253cf78715cSZi Xuan Wu 
254cf78715cSZi Xuan Wu   Register VReg = RegInfo.createVirtualRegister(RC);
255cf78715cSZi Xuan Wu   RegInfo.addLiveIn(VA.getLocReg(), VReg);
256cf78715cSZi Xuan Wu   Val = DAG.getCopyFromReg(Chain, DL, VReg, LocVT);
257cf78715cSZi Xuan Wu 
258cf78715cSZi Xuan Wu   return convertLocVTToValVT(DAG, Val, VA, DL);
259cf78715cSZi Xuan Wu }
260cf78715cSZi Xuan Wu 
261cf78715cSZi Xuan Wu static SDValue unpackFromMemLoc(SelectionDAG &DAG, SDValue Chain,
262cf78715cSZi Xuan Wu                                 const CCValAssign &VA, const SDLoc &DL) {
263cf78715cSZi Xuan Wu   MachineFunction &MF = DAG.getMachineFunction();
264cf78715cSZi Xuan Wu   MachineFrameInfo &MFI = MF.getFrameInfo();
265cf78715cSZi Xuan Wu   EVT LocVT = VA.getLocVT();
266cf78715cSZi Xuan Wu   EVT ValVT = VA.getValVT();
267cf78715cSZi Xuan Wu   EVT PtrVT = MVT::getIntegerVT(DAG.getDataLayout().getPointerSizeInBits(0));
268cf78715cSZi Xuan Wu   int FI = MFI.CreateFixedObject(ValVT.getSizeInBits() / 8,
269cf78715cSZi Xuan Wu                                  VA.getLocMemOffset(), /*Immutable=*/true);
270cf78715cSZi Xuan Wu   SDValue FIN = DAG.getFrameIndex(FI, PtrVT);
271cf78715cSZi Xuan Wu   SDValue Val;
272cf78715cSZi Xuan Wu 
273cf78715cSZi Xuan Wu   ISD::LoadExtType ExtType;
274cf78715cSZi Xuan Wu   switch (VA.getLocInfo()) {
275cf78715cSZi Xuan Wu   default:
276cf78715cSZi Xuan Wu     llvm_unreachable("Unexpected CCValAssign::LocInfo");
277cf78715cSZi Xuan Wu   case CCValAssign::Full:
278cf78715cSZi Xuan Wu   case CCValAssign::BCvt:
279cf78715cSZi Xuan Wu     ExtType = ISD::NON_EXTLOAD;
280cf78715cSZi Xuan Wu     break;
281cf78715cSZi Xuan Wu   }
282cf78715cSZi Xuan Wu   Val = DAG.getExtLoad(
283cf78715cSZi Xuan Wu       ExtType, DL, LocVT, Chain, FIN,
284cf78715cSZi Xuan Wu       MachinePointerInfo::getFixedStack(DAG.getMachineFunction(), FI), ValVT);
285cf78715cSZi Xuan Wu   return Val;
286cf78715cSZi Xuan Wu }
287cf78715cSZi Xuan Wu 
2888ddc8169SZi Xuan Wu static SDValue unpack64(SelectionDAG &DAG, SDValue Chain, const CCValAssign &VA,
2898ddc8169SZi Xuan Wu                         const SDLoc &DL) {
2908ddc8169SZi Xuan Wu   assert(VA.getLocVT() == MVT::i32 &&
2918ddc8169SZi Xuan Wu          (VA.getValVT() == MVT::f64 || VA.getValVT() == MVT::i64) &&
2928ddc8169SZi Xuan Wu          "Unexpected VA");
2938ddc8169SZi Xuan Wu   MachineFunction &MF = DAG.getMachineFunction();
2948ddc8169SZi Xuan Wu   MachineFrameInfo &MFI = MF.getFrameInfo();
2958ddc8169SZi Xuan Wu   MachineRegisterInfo &RegInfo = MF.getRegInfo();
2968ddc8169SZi Xuan Wu 
2978ddc8169SZi Xuan Wu   if (VA.isMemLoc()) {
2988ddc8169SZi Xuan Wu     // f64/i64 is passed on the stack.
2998ddc8169SZi Xuan Wu     int FI = MFI.CreateFixedObject(8, VA.getLocMemOffset(), /*Immutable=*/true);
3008ddc8169SZi Xuan Wu     SDValue FIN = DAG.getFrameIndex(FI, MVT::i32);
3018ddc8169SZi Xuan Wu     return DAG.getLoad(VA.getValVT(), DL, Chain, FIN,
3028ddc8169SZi Xuan Wu                        MachinePointerInfo::getFixedStack(MF, FI));
3038ddc8169SZi Xuan Wu   }
3048ddc8169SZi Xuan Wu 
3058ddc8169SZi Xuan Wu   assert(VA.isRegLoc() && "Expected register VA assignment");
3068ddc8169SZi Xuan Wu 
3078ddc8169SZi Xuan Wu   Register LoVReg = RegInfo.createVirtualRegister(&CSKY::GPRRegClass);
3088ddc8169SZi Xuan Wu   RegInfo.addLiveIn(VA.getLocReg(), LoVReg);
3098ddc8169SZi Xuan Wu   SDValue Lo = DAG.getCopyFromReg(Chain, DL, LoVReg, MVT::i32);
3108ddc8169SZi Xuan Wu   SDValue Hi;
3118ddc8169SZi Xuan Wu   if (VA.getLocReg() == CSKY::R3) {
3128ddc8169SZi Xuan Wu     // Second half of f64/i64 is passed on the stack.
3138ddc8169SZi Xuan Wu     int FI = MFI.CreateFixedObject(4, 0, /*Immutable=*/true);
3148ddc8169SZi Xuan Wu     SDValue FIN = DAG.getFrameIndex(FI, MVT::i32);
3158ddc8169SZi Xuan Wu     Hi = DAG.getLoad(MVT::i32, DL, Chain, FIN,
3168ddc8169SZi Xuan Wu                      MachinePointerInfo::getFixedStack(MF, FI));
3178ddc8169SZi Xuan Wu   } else {
3188ddc8169SZi Xuan Wu     // Second half of f64/i64 is passed in another GPR.
3198ddc8169SZi Xuan Wu     Register HiVReg = RegInfo.createVirtualRegister(&CSKY::GPRRegClass);
3208ddc8169SZi Xuan Wu     RegInfo.addLiveIn(VA.getLocReg() + 1, HiVReg);
3218ddc8169SZi Xuan Wu     Hi = DAG.getCopyFromReg(Chain, DL, HiVReg, MVT::i32);
3228ddc8169SZi Xuan Wu   }
3238ddc8169SZi Xuan Wu   return DAG.getNode(CSKYISD::BITCAST_FROM_LOHI, DL, VA.getValVT(), Lo, Hi);
3248ddc8169SZi Xuan Wu }
3258ddc8169SZi Xuan Wu 
326cf78715cSZi Xuan Wu // Transform physical registers into virtual registers.
327cf78715cSZi Xuan Wu SDValue CSKYTargetLowering::LowerFormalArguments(
328cf78715cSZi Xuan Wu     SDValue Chain, CallingConv::ID CallConv, bool IsVarArg,
329cf78715cSZi Xuan Wu     const SmallVectorImpl<ISD::InputArg> &Ins, const SDLoc &DL,
330cf78715cSZi Xuan Wu     SelectionDAG &DAG, SmallVectorImpl<SDValue> &InVals) const {
331cf78715cSZi Xuan Wu 
332cf78715cSZi Xuan Wu   switch (CallConv) {
333cf78715cSZi Xuan Wu   default:
334cf78715cSZi Xuan Wu     report_fatal_error("Unsupported calling convention");
335cf78715cSZi Xuan Wu   case CallingConv::C:
336cf78715cSZi Xuan Wu   case CallingConv::Fast:
337cf78715cSZi Xuan Wu     break;
338cf78715cSZi Xuan Wu   }
339cf78715cSZi Xuan Wu 
340cf78715cSZi Xuan Wu   MachineFunction &MF = DAG.getMachineFunction();
341cf78715cSZi Xuan Wu 
342cf78715cSZi Xuan Wu   // Used with vargs to acumulate store chains.
343cf78715cSZi Xuan Wu   std::vector<SDValue> OutChains;
344cf78715cSZi Xuan Wu 
345cf78715cSZi Xuan Wu   // Assign locations to all of the incoming arguments.
346cf78715cSZi Xuan Wu   SmallVector<CCValAssign, 16> ArgLocs;
347cf78715cSZi Xuan Wu   CCState CCInfo(CallConv, IsVarArg, MF, ArgLocs, *DAG.getContext());
348cf78715cSZi Xuan Wu 
349cf78715cSZi Xuan Wu   CCInfo.AnalyzeFormalArguments(Ins, CCAssignFnForCall(CallConv, IsVarArg));
350cf78715cSZi Xuan Wu 
351cf78715cSZi Xuan Wu   for (unsigned i = 0, e = ArgLocs.size(); i != e; ++i) {
352cf78715cSZi Xuan Wu     CCValAssign &VA = ArgLocs[i];
353cf78715cSZi Xuan Wu     SDValue ArgValue;
354cf78715cSZi Xuan Wu 
3558ddc8169SZi Xuan Wu     bool IsF64OnCSKY = VA.getLocVT() == MVT::i32 && VA.getValVT() == MVT::f64;
3568ddc8169SZi Xuan Wu 
3578ddc8169SZi Xuan Wu     if (IsF64OnCSKY)
3588ddc8169SZi Xuan Wu       ArgValue = unpack64(DAG, Chain, VA, DL);
3598ddc8169SZi Xuan Wu     else if (VA.isRegLoc())
360cf78715cSZi Xuan Wu       ArgValue = unpackFromRegLoc(Subtarget, DAG, Chain, VA, DL);
361cf78715cSZi Xuan Wu     else
362cf78715cSZi Xuan Wu       ArgValue = unpackFromMemLoc(DAG, Chain, VA, DL);
363cf78715cSZi Xuan Wu 
364cf78715cSZi Xuan Wu     InVals.push_back(ArgValue);
365cf78715cSZi Xuan Wu   }
366cf78715cSZi Xuan Wu 
367cf78715cSZi Xuan Wu   if (IsVarArg) {
368cf78715cSZi Xuan Wu     const unsigned XLenInBytes = 4;
369cf78715cSZi Xuan Wu     const MVT XLenVT = MVT::i32;
370cf78715cSZi Xuan Wu 
37138818b60Sserge-sans-paille     ArrayRef<MCPhysReg> ArgRegs = ArrayRef(GPRArgRegs);
372cf78715cSZi Xuan Wu     unsigned Idx = CCInfo.getFirstUnallocated(ArgRegs);
373cf78715cSZi Xuan Wu     const TargetRegisterClass *RC = &CSKY::GPRRegClass;
374cf78715cSZi Xuan Wu     MachineFrameInfo &MFI = MF.getFrameInfo();
375cf78715cSZi Xuan Wu     MachineRegisterInfo &RegInfo = MF.getRegInfo();
376cf78715cSZi Xuan Wu     CSKYMachineFunctionInfo *CSKYFI = MF.getInfo<CSKYMachineFunctionInfo>();
377cf78715cSZi Xuan Wu 
378cf78715cSZi Xuan Wu     // Offset of the first variable argument from stack pointer, and size of
379cf78715cSZi Xuan Wu     // the vararg save area. For now, the varargs save area is either zero or
380cf78715cSZi Xuan Wu     // large enough to hold a0-a4.
381cf78715cSZi Xuan Wu     int VaArgOffset, VarArgsSaveSize;
382cf78715cSZi Xuan Wu 
383cf78715cSZi Xuan Wu     // If all registers are allocated, then all varargs must be passed on the
384cf78715cSZi Xuan Wu     // stack and we don't need to save any argregs.
385cf78715cSZi Xuan Wu     if (ArgRegs.size() == Idx) {
38601a79674SSergei Barannikov       VaArgOffset = CCInfo.getStackSize();
387cf78715cSZi Xuan Wu       VarArgsSaveSize = 0;
388cf78715cSZi Xuan Wu     } else {
389cf78715cSZi Xuan Wu       VarArgsSaveSize = XLenInBytes * (ArgRegs.size() - Idx);
390cf78715cSZi Xuan Wu       VaArgOffset = -VarArgsSaveSize;
391cf78715cSZi Xuan Wu     }
392cf78715cSZi Xuan Wu 
393cf78715cSZi Xuan Wu     // Record the frame index of the first variable argument
394cf78715cSZi Xuan Wu     // which is a value necessary to VASTART.
395cf78715cSZi Xuan Wu     int FI = MFI.CreateFixedObject(XLenInBytes, VaArgOffset, true);
396cf78715cSZi Xuan Wu     CSKYFI->setVarArgsFrameIndex(FI);
397cf78715cSZi Xuan Wu 
398cf78715cSZi Xuan Wu     // Copy the integer registers that may have been used for passing varargs
399cf78715cSZi Xuan Wu     // to the vararg save area.
400cf78715cSZi Xuan Wu     for (unsigned I = Idx; I < ArgRegs.size();
401cf78715cSZi Xuan Wu          ++I, VaArgOffset += XLenInBytes) {
402cf78715cSZi Xuan Wu       const Register Reg = RegInfo.createVirtualRegister(RC);
403cf78715cSZi Xuan Wu       RegInfo.addLiveIn(ArgRegs[I], Reg);
404cf78715cSZi Xuan Wu       SDValue ArgValue = DAG.getCopyFromReg(Chain, DL, Reg, XLenVT);
405cf78715cSZi Xuan Wu       FI = MFI.CreateFixedObject(XLenInBytes, VaArgOffset, true);
406cf78715cSZi Xuan Wu       SDValue PtrOff = DAG.getFrameIndex(FI, getPointerTy(DAG.getDataLayout()));
407cf78715cSZi Xuan Wu       SDValue Store = DAG.getStore(Chain, DL, ArgValue, PtrOff,
408cf78715cSZi Xuan Wu                                    MachinePointerInfo::getFixedStack(MF, FI));
409cf78715cSZi Xuan Wu       cast<StoreSDNode>(Store.getNode())
410cf78715cSZi Xuan Wu           ->getMemOperand()
411cf78715cSZi Xuan Wu           ->setValue((Value *)nullptr);
412cf78715cSZi Xuan Wu       OutChains.push_back(Store);
413cf78715cSZi Xuan Wu     }
414cf78715cSZi Xuan Wu     CSKYFI->setVarArgsSaveSize(VarArgsSaveSize);
415cf78715cSZi Xuan Wu   }
416cf78715cSZi Xuan Wu 
417cf78715cSZi Xuan Wu   // All stores are grouped in one node to allow the matching between
418cf78715cSZi Xuan Wu   // the size of Ins and InVals. This only happens for vararg functions.
419cf78715cSZi Xuan Wu   if (!OutChains.empty()) {
420cf78715cSZi Xuan Wu     OutChains.push_back(Chain);
421cf78715cSZi Xuan Wu     Chain = DAG.getNode(ISD::TokenFactor, DL, MVT::Other, OutChains);
422cf78715cSZi Xuan Wu   }
423cf78715cSZi Xuan Wu 
424cf78715cSZi Xuan Wu   return Chain;
425cf78715cSZi Xuan Wu }
426cf78715cSZi Xuan Wu 
427cf78715cSZi Xuan Wu bool CSKYTargetLowering::CanLowerReturn(
428cf78715cSZi Xuan Wu     CallingConv::ID CallConv, MachineFunction &MF, bool IsVarArg,
429*754ed95bSyingopq     const SmallVectorImpl<ISD::OutputArg> &Outs, LLVMContext &Context,
430*754ed95bSyingopq     const Type *RetTy) const {
431cf78715cSZi Xuan Wu   SmallVector<CCValAssign, 16> CSKYLocs;
432cf78715cSZi Xuan Wu   CCState CCInfo(CallConv, IsVarArg, MF, CSKYLocs, Context);
433cf78715cSZi Xuan Wu   return CCInfo.CheckReturn(Outs, CCAssignFnForReturn(CallConv, IsVarArg));
434cf78715cSZi Xuan Wu }
435cf78715cSZi Xuan Wu 
436cf78715cSZi Xuan Wu SDValue
437cf78715cSZi Xuan Wu CSKYTargetLowering::LowerReturn(SDValue Chain, CallingConv::ID CallConv,
438cf78715cSZi Xuan Wu                                 bool IsVarArg,
439cf78715cSZi Xuan Wu                                 const SmallVectorImpl<ISD::OutputArg> &Outs,
440cf78715cSZi Xuan Wu                                 const SmallVectorImpl<SDValue> &OutVals,
441cf78715cSZi Xuan Wu                                 const SDLoc &DL, SelectionDAG &DAG) const {
442cf78715cSZi Xuan Wu   // Stores the assignment of the return value to a location.
443cf78715cSZi Xuan Wu   SmallVector<CCValAssign, 16> CSKYLocs;
444cf78715cSZi Xuan Wu 
445cf78715cSZi Xuan Wu   // Info about the registers and stack slot.
446cf78715cSZi Xuan Wu   CCState CCInfo(CallConv, IsVarArg, DAG.getMachineFunction(), CSKYLocs,
447cf78715cSZi Xuan Wu                  *DAG.getContext());
448cf78715cSZi Xuan Wu   CCInfo.AnalyzeReturn(Outs, CCAssignFnForReturn(CallConv, IsVarArg));
449cf78715cSZi Xuan Wu 
450cf78715cSZi Xuan Wu   SDValue Glue;
451cf78715cSZi Xuan Wu   SmallVector<SDValue, 4> RetOps(1, Chain);
452cf78715cSZi Xuan Wu 
453cf78715cSZi Xuan Wu   // Copy the result values into the output registers.
454cf78715cSZi Xuan Wu   for (unsigned i = 0, e = CSKYLocs.size(); i < e; ++i) {
455cf78715cSZi Xuan Wu     SDValue Val = OutVals[i];
456cf78715cSZi Xuan Wu     CCValAssign &VA = CSKYLocs[i];
457cf78715cSZi Xuan Wu     assert(VA.isRegLoc() && "Can only return in registers!");
458cf78715cSZi Xuan Wu 
459cf78715cSZi Xuan Wu     bool IsF64OnCSKY = VA.getLocVT() == MVT::i32 && VA.getValVT() == MVT::f64;
460cf78715cSZi Xuan Wu 
461cf78715cSZi Xuan Wu     if (IsF64OnCSKY) {
462cf78715cSZi Xuan Wu 
463cf78715cSZi Xuan Wu       assert(VA.isRegLoc() && "Expected return via registers");
464cf78715cSZi Xuan Wu       SDValue Split64 = DAG.getNode(CSKYISD::BITCAST_TO_LOHI, DL,
465cf78715cSZi Xuan Wu                                     DAG.getVTList(MVT::i32, MVT::i32), Val);
466cf78715cSZi Xuan Wu       SDValue Lo = Split64.getValue(0);
467cf78715cSZi Xuan Wu       SDValue Hi = Split64.getValue(1);
468cf78715cSZi Xuan Wu 
469cf78715cSZi Xuan Wu       Register RegLo = VA.getLocReg();
470cf78715cSZi Xuan Wu       assert(RegLo < CSKY::R31 && "Invalid register pair");
471cf78715cSZi Xuan Wu       Register RegHi = RegLo + 1;
472cf78715cSZi Xuan Wu 
473cf78715cSZi Xuan Wu       Chain = DAG.getCopyToReg(Chain, DL, RegLo, Lo, Glue);
474cf78715cSZi Xuan Wu       Glue = Chain.getValue(1);
475cf78715cSZi Xuan Wu       RetOps.push_back(DAG.getRegister(RegLo, MVT::i32));
476cf78715cSZi Xuan Wu       Chain = DAG.getCopyToReg(Chain, DL, RegHi, Hi, Glue);
477cf78715cSZi Xuan Wu       Glue = Chain.getValue(1);
478cf78715cSZi Xuan Wu       RetOps.push_back(DAG.getRegister(RegHi, MVT::i32));
479cf78715cSZi Xuan Wu     } else {
480cf78715cSZi Xuan Wu       // Handle a 'normal' return.
481cf78715cSZi Xuan Wu       Val = convertValVTToLocVT(DAG, Val, VA, DL);
482cf78715cSZi Xuan Wu       Chain = DAG.getCopyToReg(Chain, DL, VA.getLocReg(), Val, Glue);
483cf78715cSZi Xuan Wu 
484cf78715cSZi Xuan Wu       // Guarantee that all emitted copies are stuck together.
485cf78715cSZi Xuan Wu       Glue = Chain.getValue(1);
486cf78715cSZi Xuan Wu       RetOps.push_back(DAG.getRegister(VA.getLocReg(), VA.getLocVT()));
487cf78715cSZi Xuan Wu     }
488cf78715cSZi Xuan Wu   }
489cf78715cSZi Xuan Wu 
490cf78715cSZi Xuan Wu   RetOps[0] = Chain; // Update chain.
491cf78715cSZi Xuan Wu 
492cf78715cSZi Xuan Wu   // Add the glue node if we have it.
493cf78715cSZi Xuan Wu   if (Glue.getNode()) {
494cf78715cSZi Xuan Wu     RetOps.push_back(Glue);
495cf78715cSZi Xuan Wu   }
496cf78715cSZi Xuan Wu 
497cf78715cSZi Xuan Wu   // Interrupt service routines use different return instructions.
498cf78715cSZi Xuan Wu   if (DAG.getMachineFunction().getFunction().hasFnAttribute("interrupt"))
499cf78715cSZi Xuan Wu     return DAG.getNode(CSKYISD::NIR, DL, MVT::Other, RetOps);
500cf78715cSZi Xuan Wu 
501cf78715cSZi Xuan Wu   return DAG.getNode(CSKYISD::RET, DL, MVT::Other, RetOps);
502cf78715cSZi Xuan Wu }
503cf78715cSZi Xuan Wu 
5048ddc8169SZi Xuan Wu // Lower a call to a callseq_start + CALL + callseq_end chain, and add input
5058ddc8169SZi Xuan Wu // and output parameter nodes.
5068ddc8169SZi Xuan Wu SDValue CSKYTargetLowering::LowerCall(CallLoweringInfo &CLI,
5078ddc8169SZi Xuan Wu                                       SmallVectorImpl<SDValue> &InVals) const {
5088ddc8169SZi Xuan Wu   SelectionDAG &DAG = CLI.DAG;
5098ddc8169SZi Xuan Wu   SDLoc &DL = CLI.DL;
5108ddc8169SZi Xuan Wu   SmallVectorImpl<ISD::OutputArg> &Outs = CLI.Outs;
5118ddc8169SZi Xuan Wu   SmallVectorImpl<SDValue> &OutVals = CLI.OutVals;
5128ddc8169SZi Xuan Wu   SmallVectorImpl<ISD::InputArg> &Ins = CLI.Ins;
5138ddc8169SZi Xuan Wu   SDValue Chain = CLI.Chain;
5148ddc8169SZi Xuan Wu   SDValue Callee = CLI.Callee;
5158ddc8169SZi Xuan Wu   bool &IsTailCall = CLI.IsTailCall;
5168ddc8169SZi Xuan Wu   CallingConv::ID CallConv = CLI.CallConv;
5178ddc8169SZi Xuan Wu   bool IsVarArg = CLI.IsVarArg;
5188ddc8169SZi Xuan Wu   EVT PtrVT = getPointerTy(DAG.getDataLayout());
5198ddc8169SZi Xuan Wu   MVT XLenVT = MVT::i32;
5208ddc8169SZi Xuan Wu 
5218ddc8169SZi Xuan Wu   MachineFunction &MF = DAG.getMachineFunction();
5228ddc8169SZi Xuan Wu 
5238ddc8169SZi Xuan Wu   // Analyze the operands of the call, assigning locations to each operand.
5248ddc8169SZi Xuan Wu   SmallVector<CCValAssign, 16> ArgLocs;
5258ddc8169SZi Xuan Wu   CCState ArgCCInfo(CallConv, IsVarArg, MF, ArgLocs, *DAG.getContext());
5268ddc8169SZi Xuan Wu 
5278ddc8169SZi Xuan Wu   ArgCCInfo.AnalyzeCallOperands(Outs, CCAssignFnForCall(CallConv, IsVarArg));
5288ddc8169SZi Xuan Wu 
5298ddc8169SZi Xuan Wu   // Check if it's really possible to do a tail call.
5308ddc8169SZi Xuan Wu   if (IsTailCall)
5318ddc8169SZi Xuan Wu     IsTailCall = false; // TODO: TailCallOptimization;
5328ddc8169SZi Xuan Wu 
5338ddc8169SZi Xuan Wu   if (IsTailCall)
5348ddc8169SZi Xuan Wu     ++NumTailCalls;
5358ddc8169SZi Xuan Wu   else if (CLI.CB && CLI.CB->isMustTailCall())
5368ddc8169SZi Xuan Wu     report_fatal_error("failed to perform tail call elimination on a call "
5378ddc8169SZi Xuan Wu                        "site marked musttail");
5388ddc8169SZi Xuan Wu 
5398ddc8169SZi Xuan Wu   // Get a count of how many bytes are to be pushed on the stack.
54001a79674SSergei Barannikov   unsigned NumBytes = ArgCCInfo.getStackSize();
5418ddc8169SZi Xuan Wu 
5428ddc8169SZi Xuan Wu   // Create local copies for byval args
5438ddc8169SZi Xuan Wu   SmallVector<SDValue, 8> ByValArgs;
5448ddc8169SZi Xuan Wu   for (unsigned i = 0, e = Outs.size(); i != e; ++i) {
5458ddc8169SZi Xuan Wu     ISD::ArgFlagsTy Flags = Outs[i].Flags;
5468ddc8169SZi Xuan Wu     if (!Flags.isByVal())
5478ddc8169SZi Xuan Wu       continue;
5488ddc8169SZi Xuan Wu 
5498ddc8169SZi Xuan Wu     SDValue Arg = OutVals[i];
5508ddc8169SZi Xuan Wu     unsigned Size = Flags.getByValSize();
5518ddc8169SZi Xuan Wu     Align Alignment = Flags.getNonZeroByValAlign();
5528ddc8169SZi Xuan Wu 
5538ddc8169SZi Xuan Wu     int FI =
5548ddc8169SZi Xuan Wu         MF.getFrameInfo().CreateStackObject(Size, Alignment, /*isSS=*/false);
5558ddc8169SZi Xuan Wu     SDValue FIPtr = DAG.getFrameIndex(FI, getPointerTy(DAG.getDataLayout()));
5568ddc8169SZi Xuan Wu     SDValue SizeNode = DAG.getConstant(Size, DL, XLenVT);
5578ddc8169SZi Xuan Wu 
5588ddc8169SZi Xuan Wu     Chain = DAG.getMemcpy(Chain, DL, FIPtr, Arg, SizeNode, Alignment,
5598ddc8169SZi Xuan Wu                           /*IsVolatile=*/false,
560e3b8d364SFangrui Song                           /*AlwaysInline=*/false, /*CI=*/nullptr, IsTailCall,
5618ddc8169SZi Xuan Wu                           MachinePointerInfo(), MachinePointerInfo());
5628ddc8169SZi Xuan Wu     ByValArgs.push_back(FIPtr);
5638ddc8169SZi Xuan Wu   }
5648ddc8169SZi Xuan Wu 
5658ddc8169SZi Xuan Wu   if (!IsTailCall)
5668ddc8169SZi Xuan Wu     Chain = DAG.getCALLSEQ_START(Chain, NumBytes, 0, CLI.DL);
5678ddc8169SZi Xuan Wu 
5688ddc8169SZi Xuan Wu   // Copy argument values to their designated locations.
5698ddc8169SZi Xuan Wu   SmallVector<std::pair<Register, SDValue>, 8> RegsToPass;
5708ddc8169SZi Xuan Wu   SmallVector<SDValue, 8> MemOpChains;
5718ddc8169SZi Xuan Wu   SDValue StackPtr;
5728ddc8169SZi Xuan Wu   for (unsigned i = 0, j = 0, e = ArgLocs.size(); i != e; ++i) {
5738ddc8169SZi Xuan Wu     CCValAssign &VA = ArgLocs[i];
5748ddc8169SZi Xuan Wu     SDValue ArgValue = OutVals[i];
5758ddc8169SZi Xuan Wu     ISD::ArgFlagsTy Flags = Outs[i].Flags;
5768ddc8169SZi Xuan Wu 
5778ddc8169SZi Xuan Wu     bool IsF64OnCSKY = VA.getLocVT() == MVT::i32 && VA.getValVT() == MVT::f64;
5788ddc8169SZi Xuan Wu 
5798ddc8169SZi Xuan Wu     if (IsF64OnCSKY && VA.isRegLoc()) {
5808ddc8169SZi Xuan Wu       SDValue Split64 =
5818ddc8169SZi Xuan Wu           DAG.getNode(CSKYISD::BITCAST_TO_LOHI, DL,
5828ddc8169SZi Xuan Wu                       DAG.getVTList(MVT::i32, MVT::i32), ArgValue);
5838ddc8169SZi Xuan Wu       SDValue Lo = Split64.getValue(0);
5848ddc8169SZi Xuan Wu       SDValue Hi = Split64.getValue(1);
5858ddc8169SZi Xuan Wu 
5868ddc8169SZi Xuan Wu       Register RegLo = VA.getLocReg();
5878ddc8169SZi Xuan Wu       RegsToPass.push_back(std::make_pair(RegLo, Lo));
5888ddc8169SZi Xuan Wu 
5898ddc8169SZi Xuan Wu       if (RegLo == CSKY::R3) {
5908ddc8169SZi Xuan Wu         // Second half of f64/i64 is passed on the stack.
5918ddc8169SZi Xuan Wu         // Work out the address of the stack slot.
5928ddc8169SZi Xuan Wu         if (!StackPtr.getNode())
5938ddc8169SZi Xuan Wu           StackPtr = DAG.getCopyFromReg(Chain, DL, CSKY::R14, PtrVT);
5948ddc8169SZi Xuan Wu         // Emit the store.
5958ddc8169SZi Xuan Wu         MemOpChains.push_back(
5968ddc8169SZi Xuan Wu             DAG.getStore(Chain, DL, Hi, StackPtr, MachinePointerInfo()));
5978ddc8169SZi Xuan Wu       } else {
5988ddc8169SZi Xuan Wu         // Second half of f64/i64 is passed in another GPR.
5998ddc8169SZi Xuan Wu         assert(RegLo < CSKY::R31 && "Invalid register pair");
6008ddc8169SZi Xuan Wu         Register RegHigh = RegLo + 1;
6018ddc8169SZi Xuan Wu         RegsToPass.push_back(std::make_pair(RegHigh, Hi));
6028ddc8169SZi Xuan Wu       }
6038ddc8169SZi Xuan Wu       continue;
6048ddc8169SZi Xuan Wu     }
6058ddc8169SZi Xuan Wu 
6068ddc8169SZi Xuan Wu     ArgValue = convertValVTToLocVT(DAG, ArgValue, VA, DL);
6078ddc8169SZi Xuan Wu 
6088ddc8169SZi Xuan Wu     // Use local copy if it is a byval arg.
6098ddc8169SZi Xuan Wu     if (Flags.isByVal())
6108ddc8169SZi Xuan Wu       ArgValue = ByValArgs[j++];
6118ddc8169SZi Xuan Wu 
6128ddc8169SZi Xuan Wu     if (VA.isRegLoc()) {
6138ddc8169SZi Xuan Wu       // Queue up the argument copies and emit them at the end.
6148ddc8169SZi Xuan Wu       RegsToPass.push_back(std::make_pair(VA.getLocReg(), ArgValue));
6158ddc8169SZi Xuan Wu     } else {
6168ddc8169SZi Xuan Wu       assert(VA.isMemLoc() && "Argument not register or memory");
6178ddc8169SZi Xuan Wu       assert(!IsTailCall && "Tail call not allowed if stack is used "
6188ddc8169SZi Xuan Wu                             "for passing parameters");
6198ddc8169SZi Xuan Wu 
6208ddc8169SZi Xuan Wu       // Work out the address of the stack slot.
6218ddc8169SZi Xuan Wu       if (!StackPtr.getNode())
6228ddc8169SZi Xuan Wu         StackPtr = DAG.getCopyFromReg(Chain, DL, CSKY::R14, PtrVT);
6238ddc8169SZi Xuan Wu       SDValue Address =
6248ddc8169SZi Xuan Wu           DAG.getNode(ISD::ADD, DL, PtrVT, StackPtr,
6258ddc8169SZi Xuan Wu                       DAG.getIntPtrConstant(VA.getLocMemOffset(), DL));
6268ddc8169SZi Xuan Wu 
6278ddc8169SZi Xuan Wu       // Emit the store.
6288ddc8169SZi Xuan Wu       MemOpChains.push_back(
6298ddc8169SZi Xuan Wu           DAG.getStore(Chain, DL, ArgValue, Address, MachinePointerInfo()));
6308ddc8169SZi Xuan Wu     }
6318ddc8169SZi Xuan Wu   }
6328ddc8169SZi Xuan Wu 
6338ddc8169SZi Xuan Wu   // Join the stores, which are independent of one another.
6348ddc8169SZi Xuan Wu   if (!MemOpChains.empty())
6358ddc8169SZi Xuan Wu     Chain = DAG.getNode(ISD::TokenFactor, DL, MVT::Other, MemOpChains);
6368ddc8169SZi Xuan Wu 
6378ddc8169SZi Xuan Wu   SDValue Glue;
6388ddc8169SZi Xuan Wu 
6398ddc8169SZi Xuan Wu   // Build a sequence of copy-to-reg nodes, chained and glued together.
6408ddc8169SZi Xuan Wu   for (auto &Reg : RegsToPass) {
6418ddc8169SZi Xuan Wu     Chain = DAG.getCopyToReg(Chain, DL, Reg.first, Reg.second, Glue);
6428ddc8169SZi Xuan Wu     Glue = Chain.getValue(1);
6438ddc8169SZi Xuan Wu   }
6448ddc8169SZi Xuan Wu 
6458ddc8169SZi Xuan Wu   SmallVector<SDValue, 8> Ops;
6468ddc8169SZi Xuan Wu   EVT Ty = getPointerTy(DAG.getDataLayout());
6478ddc8169SZi Xuan Wu   bool IsRegCall = false;
6488ddc8169SZi Xuan Wu 
6498ddc8169SZi Xuan Wu   Ops.push_back(Chain);
6508ddc8169SZi Xuan Wu 
6518ddc8169SZi Xuan Wu   if (GlobalAddressSDNode *S = dyn_cast<GlobalAddressSDNode>(Callee)) {
6528ddc8169SZi Xuan Wu     const GlobalValue *GV = S->getGlobal();
65394c988bcSArthur Eubanks     bool IsLocal = getTargetMachine().shouldAssumeDSOLocal(GV);
6548ddc8169SZi Xuan Wu 
6558ddc8169SZi Xuan Wu     if (isPositionIndependent() || !Subtarget.has2E3()) {
6568ddc8169SZi Xuan Wu       IsRegCall = true;
6578ddc8169SZi Xuan Wu       Ops.push_back(getAddr<GlobalAddressSDNode, true>(S, DAG, IsLocal));
6588ddc8169SZi Xuan Wu     } else {
6598ddc8169SZi Xuan Wu       Ops.push_back(getTargetNode(cast<GlobalAddressSDNode>(Callee), DL, Ty,
6608ddc8169SZi Xuan Wu                                   DAG, CSKYII::MO_None));
6618ddc8169SZi Xuan Wu       Ops.push_back(getTargetConstantPoolValue(
6628ddc8169SZi Xuan Wu           cast<GlobalAddressSDNode>(Callee), Ty, DAG, CSKYII::MO_None));
6638ddc8169SZi Xuan Wu     }
6648ddc8169SZi Xuan Wu   } else if (ExternalSymbolSDNode *S = dyn_cast<ExternalSymbolSDNode>(Callee)) {
66594c988bcSArthur Eubanks     bool IsLocal = getTargetMachine().shouldAssumeDSOLocal(nullptr);
6668ddc8169SZi Xuan Wu 
6678ddc8169SZi Xuan Wu     if (isPositionIndependent() || !Subtarget.has2E3()) {
6688ddc8169SZi Xuan Wu       IsRegCall = true;
6698ddc8169SZi Xuan Wu       Ops.push_back(getAddr<ExternalSymbolSDNode, true>(S, DAG, IsLocal));
6708ddc8169SZi Xuan Wu     } else {
6718ddc8169SZi Xuan Wu       Ops.push_back(getTargetNode(cast<ExternalSymbolSDNode>(Callee), DL, Ty,
6728ddc8169SZi Xuan Wu                                   DAG, CSKYII::MO_None));
6738ddc8169SZi Xuan Wu       Ops.push_back(getTargetConstantPoolValue(
6748ddc8169SZi Xuan Wu           cast<ExternalSymbolSDNode>(Callee), Ty, DAG, CSKYII::MO_None));
6758ddc8169SZi Xuan Wu     }
6768ddc8169SZi Xuan Wu   } else {
6778ddc8169SZi Xuan Wu     IsRegCall = true;
6788ddc8169SZi Xuan Wu     Ops.push_back(Callee);
6798ddc8169SZi Xuan Wu   }
6808ddc8169SZi Xuan Wu 
6818ddc8169SZi Xuan Wu   // Add argument registers to the end of the list so that they are
6828ddc8169SZi Xuan Wu   // known live into the call.
6838ddc8169SZi Xuan Wu   for (auto &Reg : RegsToPass)
6848ddc8169SZi Xuan Wu     Ops.push_back(DAG.getRegister(Reg.first, Reg.second.getValueType()));
6858ddc8169SZi Xuan Wu 
6868ddc8169SZi Xuan Wu   if (!IsTailCall) {
6878ddc8169SZi Xuan Wu     // Add a register mask operand representing the call-preserved registers.
6888ddc8169SZi Xuan Wu     const TargetRegisterInfo *TRI = Subtarget.getRegisterInfo();
6898ddc8169SZi Xuan Wu     const uint32_t *Mask = TRI->getCallPreservedMask(MF, CallConv);
6908ddc8169SZi Xuan Wu     assert(Mask && "Missing call preserved mask for calling convention");
6918ddc8169SZi Xuan Wu     Ops.push_back(DAG.getRegisterMask(Mask));
6928ddc8169SZi Xuan Wu   }
6938ddc8169SZi Xuan Wu 
6948ddc8169SZi Xuan Wu   // Glue the call to the argument copies, if any.
6958ddc8169SZi Xuan Wu   if (Glue.getNode())
6968ddc8169SZi Xuan Wu     Ops.push_back(Glue);
6978ddc8169SZi Xuan Wu 
6988ddc8169SZi Xuan Wu   // Emit the call.
6998ddc8169SZi Xuan Wu   SDVTList NodeTys = DAG.getVTList(MVT::Other, MVT::Glue);
7008ddc8169SZi Xuan Wu 
7018ddc8169SZi Xuan Wu   if (IsTailCall) {
7028ddc8169SZi Xuan Wu     MF.getFrameInfo().setHasTailCall();
7038ddc8169SZi Xuan Wu     return DAG.getNode(IsRegCall ? CSKYISD::TAILReg : CSKYISD::TAIL, DL,
7048ddc8169SZi Xuan Wu                        NodeTys, Ops);
7058ddc8169SZi Xuan Wu   }
7068ddc8169SZi Xuan Wu 
7078ddc8169SZi Xuan Wu   Chain = DAG.getNode(IsRegCall ? CSKYISD::CALLReg : CSKYISD::CALL, DL, NodeTys,
7088ddc8169SZi Xuan Wu                       Ops);
7098ddc8169SZi Xuan Wu   DAG.addNoMergeSiteInfo(Chain.getNode(), CLI.NoMerge);
7108ddc8169SZi Xuan Wu   Glue = Chain.getValue(1);
7118ddc8169SZi Xuan Wu 
7128ddc8169SZi Xuan Wu   // Mark the end of the call, which is glued to the call itself.
713c6acb4ebSSergei Barannikov   Chain = DAG.getCALLSEQ_END(Chain, NumBytes, 0, Glue, DL);
7148ddc8169SZi Xuan Wu   Glue = Chain.getValue(1);
7158ddc8169SZi Xuan Wu 
7168ddc8169SZi Xuan Wu   // Assign locations to each value returned by this call.
7178ddc8169SZi Xuan Wu   SmallVector<CCValAssign, 16> CSKYLocs;
7188ddc8169SZi Xuan Wu   CCState RetCCInfo(CallConv, IsVarArg, MF, CSKYLocs, *DAG.getContext());
7198ddc8169SZi Xuan Wu   RetCCInfo.AnalyzeCallResult(Ins, CCAssignFnForReturn(CallConv, IsVarArg));
7208ddc8169SZi Xuan Wu 
7218ddc8169SZi Xuan Wu   // Copy all of the result registers out of their specified physreg.
7228ddc8169SZi Xuan Wu   for (auto &VA : CSKYLocs) {
7238ddc8169SZi Xuan Wu     // Copy the value out
7248ddc8169SZi Xuan Wu     SDValue RetValue =
7258ddc8169SZi Xuan Wu         DAG.getCopyFromReg(Chain, DL, VA.getLocReg(), VA.getLocVT(), Glue);
7268ddc8169SZi Xuan Wu     // Glue the RetValue to the end of the call sequence
7278ddc8169SZi Xuan Wu     Chain = RetValue.getValue(1);
7288ddc8169SZi Xuan Wu     Glue = RetValue.getValue(2);
7298ddc8169SZi Xuan Wu 
7308ddc8169SZi Xuan Wu     bool IsF64OnCSKY = VA.getLocVT() == MVT::i32 && VA.getValVT() == MVT::f64;
7318ddc8169SZi Xuan Wu 
7328ddc8169SZi Xuan Wu     if (IsF64OnCSKY) {
7338ddc8169SZi Xuan Wu       assert(VA.getLocReg() == GPRArgRegs[0] && "Unexpected reg assignment");
7348ddc8169SZi Xuan Wu       SDValue RetValue2 =
7358ddc8169SZi Xuan Wu           DAG.getCopyFromReg(Chain, DL, GPRArgRegs[1], MVT::i32, Glue);
7368ddc8169SZi Xuan Wu       Chain = RetValue2.getValue(1);
7378ddc8169SZi Xuan Wu       Glue = RetValue2.getValue(2);
7388ddc8169SZi Xuan Wu       RetValue = DAG.getNode(CSKYISD::BITCAST_FROM_LOHI, DL, VA.getValVT(),
7398ddc8169SZi Xuan Wu                              RetValue, RetValue2);
7408ddc8169SZi Xuan Wu     }
7418ddc8169SZi Xuan Wu 
7428ddc8169SZi Xuan Wu     RetValue = convertLocVTToValVT(DAG, RetValue, VA, DL);
7438ddc8169SZi Xuan Wu 
7448ddc8169SZi Xuan Wu     InVals.push_back(RetValue);
7458ddc8169SZi Xuan Wu   }
7468ddc8169SZi Xuan Wu 
7478ddc8169SZi Xuan Wu   return Chain;
7488ddc8169SZi Xuan Wu }
7498ddc8169SZi Xuan Wu 
750cf78715cSZi Xuan Wu CCAssignFn *CSKYTargetLowering::CCAssignFnForReturn(CallingConv::ID CC,
751cf78715cSZi Xuan Wu                                                     bool IsVarArg) const {
752cf78715cSZi Xuan Wu   if (IsVarArg || !Subtarget.useHardFloatABI())
753cf78715cSZi Xuan Wu     return RetCC_CSKY_ABIV2_SOFT;
754cf78715cSZi Xuan Wu   else
755cf78715cSZi Xuan Wu     return RetCC_CSKY_ABIV2_FP;
756cf78715cSZi Xuan Wu }
757cf78715cSZi Xuan Wu 
758cf78715cSZi Xuan Wu CCAssignFn *CSKYTargetLowering::CCAssignFnForCall(CallingConv::ID CC,
759cf78715cSZi Xuan Wu                                                   bool IsVarArg) const {
760cf78715cSZi Xuan Wu   if (IsVarArg || !Subtarget.useHardFloatABI())
761cf78715cSZi Xuan Wu     return CC_CSKY_ABIV2_SOFT;
762cf78715cSZi Xuan Wu   else
763cf78715cSZi Xuan Wu     return CC_CSKY_ABIV2_FP;
764cf78715cSZi Xuan Wu }
765cf78715cSZi Xuan Wu 
7668ddc8169SZi Xuan Wu static CSKYCP::CSKYCPModifier getModifier(unsigned Flags) {
7678ddc8169SZi Xuan Wu 
7688ddc8169SZi Xuan Wu   if (Flags == CSKYII::MO_ADDR32)
7698ddc8169SZi Xuan Wu     return CSKYCP::ADDR;
7708ddc8169SZi Xuan Wu   else if (Flags == CSKYII::MO_GOT32)
7718ddc8169SZi Xuan Wu     return CSKYCP::GOT;
7728ddc8169SZi Xuan Wu   else if (Flags == CSKYII::MO_GOTOFF)
7738ddc8169SZi Xuan Wu     return CSKYCP::GOTOFF;
7748ddc8169SZi Xuan Wu   else if (Flags == CSKYII::MO_PLT32)
7758ddc8169SZi Xuan Wu     return CSKYCP::PLT;
7768ddc8169SZi Xuan Wu   else if (Flags == CSKYII::MO_None)
7778ddc8169SZi Xuan Wu     return CSKYCP::NO_MOD;
7788ddc8169SZi Xuan Wu   else
7798ddc8169SZi Xuan Wu     assert(0 && "unknown CSKYII Modifier");
7808ddc8169SZi Xuan Wu   return CSKYCP::NO_MOD;
7818ddc8169SZi Xuan Wu }
7828ddc8169SZi Xuan Wu 
7838ddc8169SZi Xuan Wu SDValue CSKYTargetLowering::getTargetConstantPoolValue(GlobalAddressSDNode *N,
7848ddc8169SZi Xuan Wu                                                        EVT Ty,
7858ddc8169SZi Xuan Wu                                                        SelectionDAG &DAG,
7868ddc8169SZi Xuan Wu                                                        unsigned Flags) const {
7878ddc8169SZi Xuan Wu   CSKYConstantPoolValue *CPV = CSKYConstantPoolConstant::Create(
7888ddc8169SZi Xuan Wu       N->getGlobal(), CSKYCP::CPValue, 0, getModifier(Flags), false);
7898ddc8169SZi Xuan Wu 
7908ddc8169SZi Xuan Wu   return DAG.getTargetConstantPool(CPV, Ty);
7918ddc8169SZi Xuan Wu }
7928ddc8169SZi Xuan Wu 
793a190fcdfSZi Xuan Wu CSKYTargetLowering::ConstraintType
794a190fcdfSZi Xuan Wu CSKYTargetLowering::getConstraintType(StringRef Constraint) const {
795a190fcdfSZi Xuan Wu   if (Constraint.size() == 1) {
796a190fcdfSZi Xuan Wu     switch (Constraint[0]) {
797a190fcdfSZi Xuan Wu     default:
798a190fcdfSZi Xuan Wu       break;
799a190fcdfSZi Xuan Wu     case 'a':
800a190fcdfSZi Xuan Wu     case 'b':
801a190fcdfSZi Xuan Wu     case 'v':
802a190fcdfSZi Xuan Wu     case 'w':
803a190fcdfSZi Xuan Wu     case 'y':
804a190fcdfSZi Xuan Wu       return C_RegisterClass;
805a190fcdfSZi Xuan Wu     case 'c':
806a190fcdfSZi Xuan Wu     case 'l':
807a190fcdfSZi Xuan Wu     case 'h':
808a190fcdfSZi Xuan Wu     case 'z':
809a190fcdfSZi Xuan Wu       return C_Register;
810a190fcdfSZi Xuan Wu     }
811a190fcdfSZi Xuan Wu   }
812a190fcdfSZi Xuan Wu   return TargetLowering::getConstraintType(Constraint);
813a190fcdfSZi Xuan Wu }
814a190fcdfSZi Xuan Wu 
815a190fcdfSZi Xuan Wu std::pair<unsigned, const TargetRegisterClass *>
816a190fcdfSZi Xuan Wu CSKYTargetLowering::getRegForInlineAsmConstraint(const TargetRegisterInfo *TRI,
817a190fcdfSZi Xuan Wu                                                  StringRef Constraint,
818a190fcdfSZi Xuan Wu                                                  MVT VT) const {
819a190fcdfSZi Xuan Wu   if (Constraint.size() == 1) {
820a190fcdfSZi Xuan Wu     switch (Constraint[0]) {
821a190fcdfSZi Xuan Wu     case 'r':
822a190fcdfSZi Xuan Wu       return std::make_pair(0U, &CSKY::GPRRegClass);
823a190fcdfSZi Xuan Wu     case 'a':
824a190fcdfSZi Xuan Wu       return std::make_pair(0U, &CSKY::mGPRRegClass);
825a190fcdfSZi Xuan Wu     case 'b':
826a190fcdfSZi Xuan Wu       return std::make_pair(0U, &CSKY::sGPRRegClass);
827a190fcdfSZi Xuan Wu     case 'z':
828a190fcdfSZi Xuan Wu       return std::make_pair(CSKY::R14, &CSKY::GPRRegClass);
829a190fcdfSZi Xuan Wu     case 'c':
830a190fcdfSZi Xuan Wu       return std::make_pair(CSKY::C, &CSKY::CARRYRegClass);
831a190fcdfSZi Xuan Wu     case 'w':
832a190fcdfSZi Xuan Wu       if ((Subtarget.hasFPUv2SingleFloat() ||
833a190fcdfSZi Xuan Wu            Subtarget.hasFPUv3SingleFloat()) &&
834a190fcdfSZi Xuan Wu           VT == MVT::f32)
835a190fcdfSZi Xuan Wu         return std::make_pair(0U, &CSKY::sFPR32RegClass);
836a190fcdfSZi Xuan Wu       if ((Subtarget.hasFPUv2DoubleFloat() ||
837a190fcdfSZi Xuan Wu            Subtarget.hasFPUv3DoubleFloat()) &&
838a190fcdfSZi Xuan Wu           VT == MVT::f64)
839a190fcdfSZi Xuan Wu         return std::make_pair(0U, &CSKY::sFPR64RegClass);
840a190fcdfSZi Xuan Wu       break;
841a190fcdfSZi Xuan Wu     case 'v':
842a190fcdfSZi Xuan Wu       if (Subtarget.hasFPUv2SingleFloat() && VT == MVT::f32)
843a190fcdfSZi Xuan Wu         return std::make_pair(0U, &CSKY::sFPR32RegClass);
844a190fcdfSZi Xuan Wu       if (Subtarget.hasFPUv3SingleFloat() && VT == MVT::f32)
845a190fcdfSZi Xuan Wu         return std::make_pair(0U, &CSKY::FPR32RegClass);
846a190fcdfSZi Xuan Wu       if (Subtarget.hasFPUv2DoubleFloat() && VT == MVT::f64)
847a190fcdfSZi Xuan Wu         return std::make_pair(0U, &CSKY::sFPR64RegClass);
848a190fcdfSZi Xuan Wu       if (Subtarget.hasFPUv3DoubleFloat() && VT == MVT::f64)
849a190fcdfSZi Xuan Wu         return std::make_pair(0U, &CSKY::FPR64RegClass);
850a190fcdfSZi Xuan Wu       break;
851a190fcdfSZi Xuan Wu     default:
852a190fcdfSZi Xuan Wu       break;
853a190fcdfSZi Xuan Wu     }
854a190fcdfSZi Xuan Wu   }
855a190fcdfSZi Xuan Wu 
856a190fcdfSZi Xuan Wu   if (Constraint == "{c}")
857a190fcdfSZi Xuan Wu     return std::make_pair(CSKY::C, &CSKY::CARRYRegClass);
858a190fcdfSZi Xuan Wu 
859a190fcdfSZi Xuan Wu   // Clang will correctly decode the usage of register name aliases into their
860a190fcdfSZi Xuan Wu   // official names. However, other frontends like `rustc` do not. This allows
861a190fcdfSZi Xuan Wu   // users of these frontends to use the ABI names for registers in LLVM-style
862a190fcdfSZi Xuan Wu   // register constraints.
863a190fcdfSZi Xuan Wu   unsigned XRegFromAlias = StringSwitch<unsigned>(Constraint.lower())
864a190fcdfSZi Xuan Wu                                .Case("{a0}", CSKY::R0)
865a190fcdfSZi Xuan Wu                                .Case("{a1}", CSKY::R1)
866a190fcdfSZi Xuan Wu                                .Case("{a2}", CSKY::R2)
867a190fcdfSZi Xuan Wu                                .Case("{a3}", CSKY::R3)
868a190fcdfSZi Xuan Wu                                .Case("{l0}", CSKY::R4)
869a190fcdfSZi Xuan Wu                                .Case("{l1}", CSKY::R5)
870a190fcdfSZi Xuan Wu                                .Case("{l2}", CSKY::R6)
871a190fcdfSZi Xuan Wu                                .Case("{l3}", CSKY::R7)
872a190fcdfSZi Xuan Wu                                .Case("{l4}", CSKY::R8)
873a190fcdfSZi Xuan Wu                                .Case("{l5}", CSKY::R9)
874a190fcdfSZi Xuan Wu                                .Case("{l6}", CSKY::R10)
875a190fcdfSZi Xuan Wu                                .Case("{l7}", CSKY::R11)
876a190fcdfSZi Xuan Wu                                .Case("{t0}", CSKY::R12)
877a190fcdfSZi Xuan Wu                                .Case("{t1}", CSKY::R13)
878a190fcdfSZi Xuan Wu                                .Case("{sp}", CSKY::R14)
879a190fcdfSZi Xuan Wu                                .Case("{lr}", CSKY::R15)
880a190fcdfSZi Xuan Wu                                .Case("{l8}", CSKY::R16)
881a190fcdfSZi Xuan Wu                                .Case("{l9}", CSKY::R17)
882a190fcdfSZi Xuan Wu                                .Case("{t2}", CSKY::R18)
883a190fcdfSZi Xuan Wu                                .Case("{t3}", CSKY::R19)
884a190fcdfSZi Xuan Wu                                .Case("{t4}", CSKY::R20)
885a190fcdfSZi Xuan Wu                                .Case("{t5}", CSKY::R21)
886a190fcdfSZi Xuan Wu                                .Case("{t6}", CSKY::R22)
887a190fcdfSZi Xuan Wu                                .Cases("{t7}", "{fp}", CSKY::R23)
888a190fcdfSZi Xuan Wu                                .Cases("{t8}", "{top}", CSKY::R24)
889a190fcdfSZi Xuan Wu                                .Cases("{t9}", "{bsp}", CSKY::R25)
890a190fcdfSZi Xuan Wu                                .Case("{r26}", CSKY::R26)
891a190fcdfSZi Xuan Wu                                .Case("{r27}", CSKY::R27)
892a190fcdfSZi Xuan Wu                                .Cases("{gb}", "{rgb}", "{rdb}", CSKY::R28)
893a190fcdfSZi Xuan Wu                                .Cases("{tb}", "{rtb}", CSKY::R29)
894a190fcdfSZi Xuan Wu                                .Case("{svbr}", CSKY::R30)
895a190fcdfSZi Xuan Wu                                .Case("{tls}", CSKY::R31)
896a190fcdfSZi Xuan Wu                                .Default(CSKY::NoRegister);
897a190fcdfSZi Xuan Wu 
898a190fcdfSZi Xuan Wu   if (XRegFromAlias != CSKY::NoRegister)
899a190fcdfSZi Xuan Wu     return std::make_pair(XRegFromAlias, &CSKY::GPRRegClass);
900a190fcdfSZi Xuan Wu 
901a190fcdfSZi Xuan Wu   // Since TargetLowering::getRegForInlineAsmConstraint uses the name of the
902a190fcdfSZi Xuan Wu   // TableGen record rather than the AsmName to choose registers for InlineAsm
903a190fcdfSZi Xuan Wu   // constraints, plus we want to match those names to the widest floating point
904a190fcdfSZi Xuan Wu   // register type available, manually select floating point registers here.
905a190fcdfSZi Xuan Wu   //
906a190fcdfSZi Xuan Wu   // The second case is the ABI name of the register, so that frontends can also
907a190fcdfSZi Xuan Wu   // use the ABI names in register constraint lists.
908a190fcdfSZi Xuan Wu   if (Subtarget.useHardFloat()) {
909a190fcdfSZi Xuan Wu     unsigned FReg = StringSwitch<unsigned>(Constraint.lower())
910a190fcdfSZi Xuan Wu                         .Cases("{fr0}", "{vr0}", CSKY::F0_32)
911a190fcdfSZi Xuan Wu                         .Cases("{fr1}", "{vr1}", CSKY::F1_32)
912a190fcdfSZi Xuan Wu                         .Cases("{fr2}", "{vr2}", CSKY::F2_32)
913a190fcdfSZi Xuan Wu                         .Cases("{fr3}", "{vr3}", CSKY::F3_32)
914a190fcdfSZi Xuan Wu                         .Cases("{fr4}", "{vr4}", CSKY::F4_32)
915a190fcdfSZi Xuan Wu                         .Cases("{fr5}", "{vr5}", CSKY::F5_32)
916a190fcdfSZi Xuan Wu                         .Cases("{fr6}", "{vr6}", CSKY::F6_32)
917a190fcdfSZi Xuan Wu                         .Cases("{fr7}", "{vr7}", CSKY::F7_32)
918a190fcdfSZi Xuan Wu                         .Cases("{fr8}", "{vr8}", CSKY::F8_32)
919a190fcdfSZi Xuan Wu                         .Cases("{fr9}", "{vr9}", CSKY::F9_32)
920a190fcdfSZi Xuan Wu                         .Cases("{fr10}", "{vr10}", CSKY::F10_32)
921a190fcdfSZi Xuan Wu                         .Cases("{fr11}", "{vr11}", CSKY::F11_32)
922a190fcdfSZi Xuan Wu                         .Cases("{fr12}", "{vr12}", CSKY::F12_32)
923a190fcdfSZi Xuan Wu                         .Cases("{fr13}", "{vr13}", CSKY::F13_32)
924a190fcdfSZi Xuan Wu                         .Cases("{fr14}", "{vr14}", CSKY::F14_32)
925a190fcdfSZi Xuan Wu                         .Cases("{fr15}", "{vr15}", CSKY::F15_32)
926a190fcdfSZi Xuan Wu                         .Cases("{fr16}", "{vr16}", CSKY::F16_32)
927a190fcdfSZi Xuan Wu                         .Cases("{fr17}", "{vr17}", CSKY::F17_32)
928a190fcdfSZi Xuan Wu                         .Cases("{fr18}", "{vr18}", CSKY::F18_32)
929a190fcdfSZi Xuan Wu                         .Cases("{fr19}", "{vr19}", CSKY::F19_32)
930a190fcdfSZi Xuan Wu                         .Cases("{fr20}", "{vr20}", CSKY::F20_32)
931a190fcdfSZi Xuan Wu                         .Cases("{fr21}", "{vr21}", CSKY::F21_32)
932a190fcdfSZi Xuan Wu                         .Cases("{fr22}", "{vr22}", CSKY::F22_32)
933a190fcdfSZi Xuan Wu                         .Cases("{fr23}", "{vr23}", CSKY::F23_32)
934a190fcdfSZi Xuan Wu                         .Cases("{fr24}", "{vr24}", CSKY::F24_32)
935a190fcdfSZi Xuan Wu                         .Cases("{fr25}", "{vr25}", CSKY::F25_32)
936a190fcdfSZi Xuan Wu                         .Cases("{fr26}", "{vr26}", CSKY::F26_32)
937a190fcdfSZi Xuan Wu                         .Cases("{fr27}", "{vr27}", CSKY::F27_32)
938a190fcdfSZi Xuan Wu                         .Cases("{fr28}", "{vr28}", CSKY::F28_32)
939a190fcdfSZi Xuan Wu                         .Cases("{fr29}", "{vr29}", CSKY::F29_32)
940a190fcdfSZi Xuan Wu                         .Cases("{fr30}", "{vr30}", CSKY::F30_32)
941a190fcdfSZi Xuan Wu                         .Cases("{fr31}", "{vr31}", CSKY::F31_32)
942a190fcdfSZi Xuan Wu                         .Default(CSKY::NoRegister);
943a190fcdfSZi Xuan Wu     if (FReg != CSKY::NoRegister) {
944a190fcdfSZi Xuan Wu       assert(CSKY::F0_32 <= FReg && FReg <= CSKY::F31_32 && "Unknown fp-reg");
945a190fcdfSZi Xuan Wu       unsigned RegNo = FReg - CSKY::F0_32;
946a190fcdfSZi Xuan Wu       unsigned DReg = CSKY::F0_64 + RegNo;
947a190fcdfSZi Xuan Wu 
948a190fcdfSZi Xuan Wu       if (Subtarget.hasFPUv2DoubleFloat())
949a190fcdfSZi Xuan Wu         return std::make_pair(DReg, &CSKY::sFPR64RegClass);
950a190fcdfSZi Xuan Wu       else if (Subtarget.hasFPUv3DoubleFloat())
951a190fcdfSZi Xuan Wu         return std::make_pair(DReg, &CSKY::FPR64RegClass);
952a190fcdfSZi Xuan Wu       else if (Subtarget.hasFPUv2SingleFloat())
953a190fcdfSZi Xuan Wu         return std::make_pair(FReg, &CSKY::sFPR32RegClass);
954a190fcdfSZi Xuan Wu       else if (Subtarget.hasFPUv3SingleFloat())
955a190fcdfSZi Xuan Wu         return std::make_pair(FReg, &CSKY::FPR32RegClass);
956a190fcdfSZi Xuan Wu     }
957a190fcdfSZi Xuan Wu   }
958a190fcdfSZi Xuan Wu 
959a190fcdfSZi Xuan Wu   return TargetLowering::getRegForInlineAsmConstraint(TRI, Constraint, VT);
960a190fcdfSZi Xuan Wu }
961a190fcdfSZi Xuan Wu 
9628ddc8169SZi Xuan Wu static MachineBasicBlock *
9638ddc8169SZi Xuan Wu emitSelectPseudo(MachineInstr &MI, MachineBasicBlock *BB, unsigned Opcode) {
9648ddc8169SZi Xuan Wu 
9658ddc8169SZi Xuan Wu   const TargetInstrInfo &TII = *BB->getParent()->getSubtarget().getInstrInfo();
9668ddc8169SZi Xuan Wu   DebugLoc DL = MI.getDebugLoc();
9678ddc8169SZi Xuan Wu 
9688ddc8169SZi Xuan Wu   // To "insert" a SELECT instruction, we actually have to insert the
9698ddc8169SZi Xuan Wu   // diamond control-flow pattern.  The incoming instruction knows the
9708ddc8169SZi Xuan Wu   // destination vreg to set, the condition code register to branch on, the
9718ddc8169SZi Xuan Wu   // true/false values to select between, and a branch opcode to use.
9728ddc8169SZi Xuan Wu   const BasicBlock *LLVM_BB = BB->getBasicBlock();
9738ddc8169SZi Xuan Wu   MachineFunction::iterator It = ++BB->getIterator();
9748ddc8169SZi Xuan Wu 
9758ddc8169SZi Xuan Wu   //  thisMBB:
9768ddc8169SZi Xuan Wu   //  ...
9778ddc8169SZi Xuan Wu   //   TrueVal = ...
9788ddc8169SZi Xuan Wu   //   bt32 c, sinkMBB
9798ddc8169SZi Xuan Wu   //   fallthrough --> copyMBB
9808ddc8169SZi Xuan Wu   MachineBasicBlock *thisMBB = BB;
9818ddc8169SZi Xuan Wu   MachineFunction *F = BB->getParent();
9828ddc8169SZi Xuan Wu   MachineBasicBlock *copyMBB = F->CreateMachineBasicBlock(LLVM_BB);
9838ddc8169SZi Xuan Wu   MachineBasicBlock *sinkMBB = F->CreateMachineBasicBlock(LLVM_BB);
9848ddc8169SZi Xuan Wu   F->insert(It, copyMBB);
9858ddc8169SZi Xuan Wu   F->insert(It, sinkMBB);
9868ddc8169SZi Xuan Wu 
9878ddc8169SZi Xuan Wu   // Transfer the remainder of BB and its successor edges to sinkMBB.
9888ddc8169SZi Xuan Wu   sinkMBB->splice(sinkMBB->begin(), BB,
9898ddc8169SZi Xuan Wu                   std::next(MachineBasicBlock::iterator(MI)), BB->end());
9908ddc8169SZi Xuan Wu   sinkMBB->transferSuccessorsAndUpdatePHIs(BB);
9918ddc8169SZi Xuan Wu 
9928ddc8169SZi Xuan Wu   // Next, add the true and fallthrough blocks as its successors.
9938ddc8169SZi Xuan Wu   BB->addSuccessor(copyMBB);
9948ddc8169SZi Xuan Wu   BB->addSuccessor(sinkMBB);
9958ddc8169SZi Xuan Wu 
9968ddc8169SZi Xuan Wu   // bt32 condition, sinkMBB
9978ddc8169SZi Xuan Wu   BuildMI(BB, DL, TII.get(Opcode))
9988ddc8169SZi Xuan Wu       .addReg(MI.getOperand(1).getReg())
9998ddc8169SZi Xuan Wu       .addMBB(sinkMBB);
10008ddc8169SZi Xuan Wu 
10018ddc8169SZi Xuan Wu   //  copyMBB:
10028ddc8169SZi Xuan Wu   //   %FalseValue = ...
10038ddc8169SZi Xuan Wu   //   # fallthrough to sinkMBB
10048ddc8169SZi Xuan Wu   BB = copyMBB;
10058ddc8169SZi Xuan Wu 
10068ddc8169SZi Xuan Wu   // Update machine-CFG edges
10078ddc8169SZi Xuan Wu   BB->addSuccessor(sinkMBB);
10088ddc8169SZi Xuan Wu 
10098ddc8169SZi Xuan Wu   //  sinkMBB:
10108ddc8169SZi Xuan Wu   //   %Result = phi [ %TrueValue, thisMBB ], [ %FalseValue, copyMBB ]
10118ddc8169SZi Xuan Wu   //  ...
10128ddc8169SZi Xuan Wu   BB = sinkMBB;
10138ddc8169SZi Xuan Wu 
10148ddc8169SZi Xuan Wu   BuildMI(*BB, BB->begin(), DL, TII.get(CSKY::PHI), MI.getOperand(0).getReg())
10158ddc8169SZi Xuan Wu       .addReg(MI.getOperand(2).getReg())
10168ddc8169SZi Xuan Wu       .addMBB(thisMBB)
10178ddc8169SZi Xuan Wu       .addReg(MI.getOperand(3).getReg())
10188ddc8169SZi Xuan Wu       .addMBB(copyMBB);
10198ddc8169SZi Xuan Wu 
10208ddc8169SZi Xuan Wu   MI.eraseFromParent(); // The pseudo instruction is gone now.
10218ddc8169SZi Xuan Wu 
10228ddc8169SZi Xuan Wu   return BB;
10238ddc8169SZi Xuan Wu }
10248ddc8169SZi Xuan Wu 
10258ddc8169SZi Xuan Wu MachineBasicBlock *
10268ddc8169SZi Xuan Wu CSKYTargetLowering::EmitInstrWithCustomInserter(MachineInstr &MI,
10278ddc8169SZi Xuan Wu                                                 MachineBasicBlock *BB) const {
10288ddc8169SZi Xuan Wu   switch (MI.getOpcode()) {
10298ddc8169SZi Xuan Wu   default:
10308ddc8169SZi Xuan Wu     llvm_unreachable("Unexpected instr type to insert");
1031208f93c1SZi Xuan Wu   case CSKY::FSELS:
1032208f93c1SZi Xuan Wu   case CSKY::FSELD:
1033208f93c1SZi Xuan Wu     if (Subtarget.hasE2())
1034208f93c1SZi Xuan Wu       return emitSelectPseudo(MI, BB, CSKY::BT32);
1035208f93c1SZi Xuan Wu     else
1036208f93c1SZi Xuan Wu       return emitSelectPseudo(MI, BB, CSKY::BT16);
10378ddc8169SZi Xuan Wu   case CSKY::ISEL32:
10388ddc8169SZi Xuan Wu     return emitSelectPseudo(MI, BB, CSKY::BT32);
10398ddc8169SZi Xuan Wu   case CSKY::ISEL16:
10408ddc8169SZi Xuan Wu     return emitSelectPseudo(MI, BB, CSKY::BT16);
10418ddc8169SZi Xuan Wu   }
10428ddc8169SZi Xuan Wu }
10438ddc8169SZi Xuan Wu 
10448ddc8169SZi Xuan Wu SDValue CSKYTargetLowering::getTargetConstantPoolValue(ExternalSymbolSDNode *N,
10458ddc8169SZi Xuan Wu                                                        EVT Ty,
10468ddc8169SZi Xuan Wu                                                        SelectionDAG &DAG,
10478ddc8169SZi Xuan Wu                                                        unsigned Flags) const {
10488ddc8169SZi Xuan Wu   CSKYConstantPoolValue *CPV =
10498ddc8169SZi Xuan Wu       CSKYConstantPoolSymbol::Create(Type::getInt32Ty(*DAG.getContext()),
10508ddc8169SZi Xuan Wu                                      N->getSymbol(), 0, getModifier(Flags));
10518ddc8169SZi Xuan Wu 
10528ddc8169SZi Xuan Wu   return DAG.getTargetConstantPool(CPV, Ty);
10538ddc8169SZi Xuan Wu }
10548ddc8169SZi Xuan Wu 
10558ddc8169SZi Xuan Wu SDValue CSKYTargetLowering::getTargetConstantPoolValue(JumpTableSDNode *N,
10568ddc8169SZi Xuan Wu                                                        EVT Ty,
10578ddc8169SZi Xuan Wu                                                        SelectionDAG &DAG,
10588ddc8169SZi Xuan Wu                                                        unsigned Flags) const {
10598ddc8169SZi Xuan Wu   CSKYConstantPoolValue *CPV =
10608ddc8169SZi Xuan Wu       CSKYConstantPoolJT::Create(Type::getInt32Ty(*DAG.getContext()),
10618ddc8169SZi Xuan Wu                                  N->getIndex(), 0, getModifier(Flags));
10628ddc8169SZi Xuan Wu   return DAG.getTargetConstantPool(CPV, Ty);
10638ddc8169SZi Xuan Wu }
10648ddc8169SZi Xuan Wu 
10658ddc8169SZi Xuan Wu SDValue CSKYTargetLowering::getTargetConstantPoolValue(BlockAddressSDNode *N,
10668ddc8169SZi Xuan Wu                                                        EVT Ty,
10678ddc8169SZi Xuan Wu                                                        SelectionDAG &DAG,
10688ddc8169SZi Xuan Wu                                                        unsigned Flags) const {
1069f4d61cdfSZi Xuan Wu (Zeson)   assert(N->getOffset() == 0);
10708ddc8169SZi Xuan Wu   CSKYConstantPoolValue *CPV = CSKYConstantPoolConstant::Create(
10718ddc8169SZi Xuan Wu       N->getBlockAddress(), CSKYCP::CPBlockAddress, 0, getModifier(Flags),
10728ddc8169SZi Xuan Wu       false);
10738ddc8169SZi Xuan Wu   return DAG.getTargetConstantPool(CPV, Ty);
10748ddc8169SZi Xuan Wu }
10758ddc8169SZi Xuan Wu 
1076f4d61cdfSZi Xuan Wu (Zeson) SDValue CSKYTargetLowering::getTargetConstantPoolValue(ConstantPoolSDNode *N,
1077f4d61cdfSZi Xuan Wu (Zeson)                                                        EVT Ty,
1078f4d61cdfSZi Xuan Wu (Zeson)                                                        SelectionDAG &DAG,
1079f4d61cdfSZi Xuan Wu (Zeson)                                                        unsigned Flags) const {
1080f4d61cdfSZi Xuan Wu (Zeson)   assert(N->getOffset() == 0);
1081f4d61cdfSZi Xuan Wu (Zeson)   CSKYConstantPoolValue *CPV = CSKYConstantPoolConstant::Create(
1082f4d61cdfSZi Xuan Wu (Zeson)       N->getConstVal(), Type::getInt32Ty(*DAG.getContext()),
1083f4d61cdfSZi Xuan Wu (Zeson)       CSKYCP::CPConstPool, 0, getModifier(Flags), false);
1084f4d61cdfSZi Xuan Wu (Zeson)   return DAG.getTargetConstantPool(CPV, Ty);
1085f4d61cdfSZi Xuan Wu (Zeson) }
1086f4d61cdfSZi Xuan Wu (Zeson) 
10878ddc8169SZi Xuan Wu SDValue CSKYTargetLowering::getTargetNode(GlobalAddressSDNode *N, SDLoc DL,
10888ddc8169SZi Xuan Wu                                           EVT Ty, SelectionDAG &DAG,
10898ddc8169SZi Xuan Wu                                           unsigned Flags) const {
10908ddc8169SZi Xuan Wu   return DAG.getTargetGlobalAddress(N->getGlobal(), DL, Ty, 0, Flags);
10918ddc8169SZi Xuan Wu }
10928ddc8169SZi Xuan Wu 
10938ddc8169SZi Xuan Wu SDValue CSKYTargetLowering::getTargetNode(ExternalSymbolSDNode *N, SDLoc DL,
10948ddc8169SZi Xuan Wu                                           EVT Ty, SelectionDAG &DAG,
10958ddc8169SZi Xuan Wu                                           unsigned Flags) const {
10968ddc8169SZi Xuan Wu   return DAG.getTargetExternalSymbol(N->getSymbol(), Ty, Flags);
10978ddc8169SZi Xuan Wu }
10988ddc8169SZi Xuan Wu 
10998ddc8169SZi Xuan Wu SDValue CSKYTargetLowering::getTargetNode(JumpTableSDNode *N, SDLoc DL, EVT Ty,
11008ddc8169SZi Xuan Wu                                           SelectionDAG &DAG,
11018ddc8169SZi Xuan Wu                                           unsigned Flags) const {
11028ddc8169SZi Xuan Wu   return DAG.getTargetJumpTable(N->getIndex(), Ty, Flags);
11038ddc8169SZi Xuan Wu }
11048ddc8169SZi Xuan Wu 
11058ddc8169SZi Xuan Wu SDValue CSKYTargetLowering::getTargetNode(BlockAddressSDNode *N, SDLoc DL,
11068ddc8169SZi Xuan Wu                                           EVT Ty, SelectionDAG &DAG,
11078ddc8169SZi Xuan Wu                                           unsigned Flags) const {
11088ddc8169SZi Xuan Wu   return DAG.getTargetBlockAddress(N->getBlockAddress(), Ty, N->getOffset(),
11098ddc8169SZi Xuan Wu                                    Flags);
11108ddc8169SZi Xuan Wu }
11118ddc8169SZi Xuan Wu 
1112f4d61cdfSZi Xuan Wu (Zeson) SDValue CSKYTargetLowering::getTargetNode(ConstantPoolSDNode *N, SDLoc DL,
1113f4d61cdfSZi Xuan Wu (Zeson)                                           EVT Ty, SelectionDAG &DAG,
1114f4d61cdfSZi Xuan Wu (Zeson)                                           unsigned Flags) const {
1115f4d61cdfSZi Xuan Wu (Zeson) 
1116f4d61cdfSZi Xuan Wu (Zeson)   return DAG.getTargetConstantPool(N->getConstVal(), Ty, N->getAlign(),
1117f4d61cdfSZi Xuan Wu (Zeson)                                    N->getOffset(), Flags);
1118f4d61cdfSZi Xuan Wu (Zeson) }
1119f4d61cdfSZi Xuan Wu (Zeson) 
1120cf78715cSZi Xuan Wu const char *CSKYTargetLowering::getTargetNodeName(unsigned Opcode) const {
1121cf78715cSZi Xuan Wu   switch (Opcode) {
1122cf78715cSZi Xuan Wu   default:
1123cf78715cSZi Xuan Wu     llvm_unreachable("unknown CSKYISD node");
1124cf78715cSZi Xuan Wu   case CSKYISD::NIE:
1125cf78715cSZi Xuan Wu     return "CSKYISD::NIE";
1126cf78715cSZi Xuan Wu   case CSKYISD::NIR:
1127cf78715cSZi Xuan Wu     return "CSKYISD::NIR";
1128cf78715cSZi Xuan Wu   case CSKYISD::RET:
1129cf78715cSZi Xuan Wu     return "CSKYISD::RET";
11308ddc8169SZi Xuan Wu   case CSKYISD::CALL:
11318ddc8169SZi Xuan Wu     return "CSKYISD::CALL";
11328ddc8169SZi Xuan Wu   case CSKYISD::CALLReg:
11338ddc8169SZi Xuan Wu     return "CSKYISD::CALLReg";
11348ddc8169SZi Xuan Wu   case CSKYISD::TAIL:
11358ddc8169SZi Xuan Wu     return "CSKYISD::TAIL";
11368ddc8169SZi Xuan Wu   case CSKYISD::TAILReg:
11378ddc8169SZi Xuan Wu     return "CSKYISD::TAILReg";
11388ddc8169SZi Xuan Wu   case CSKYISD::LOAD_ADDR:
11398ddc8169SZi Xuan Wu     return "CSKYISD::LOAD_ADDR";
1140cf78715cSZi Xuan Wu   case CSKYISD::BITCAST_TO_LOHI:
1141cf78715cSZi Xuan Wu     return "CSKYISD::BITCAST_TO_LOHI";
11428ddc8169SZi Xuan Wu   case CSKYISD::BITCAST_FROM_LOHI:
11438ddc8169SZi Xuan Wu     return "CSKYISD::BITCAST_FROM_LOHI";
1144cf78715cSZi Xuan Wu   }
1145cf78715cSZi Xuan Wu }
11468ddc8169SZi Xuan Wu 
11478ddc8169SZi Xuan Wu SDValue CSKYTargetLowering::LowerGlobalAddress(SDValue Op,
11488ddc8169SZi Xuan Wu                                                SelectionDAG &DAG) const {
11498ddc8169SZi Xuan Wu   SDLoc DL(Op);
11508ddc8169SZi Xuan Wu   EVT Ty = Op.getValueType();
11518ddc8169SZi Xuan Wu   GlobalAddressSDNode *N = cast<GlobalAddressSDNode>(Op);
11528ddc8169SZi Xuan Wu   int64_t Offset = N->getOffset();
11538ddc8169SZi Xuan Wu 
11548ddc8169SZi Xuan Wu   const GlobalValue *GV = N->getGlobal();
115594c988bcSArthur Eubanks   bool IsLocal = getTargetMachine().shouldAssumeDSOLocal(GV);
11568ddc8169SZi Xuan Wu   SDValue Addr = getAddr<GlobalAddressSDNode, false>(N, DAG, IsLocal);
11578ddc8169SZi Xuan Wu 
11588ddc8169SZi Xuan Wu   // In order to maximise the opportunity for common subexpression elimination,
11598ddc8169SZi Xuan Wu   // emit a separate ADD node for the global address offset instead of folding
11608ddc8169SZi Xuan Wu   // it in the global address node. Later peephole optimisations may choose to
11618ddc8169SZi Xuan Wu   // fold it back in when profitable.
11628ddc8169SZi Xuan Wu   if (Offset != 0)
11638ddc8169SZi Xuan Wu     return DAG.getNode(ISD::ADD, DL, Ty, Addr,
11648ddc8169SZi Xuan Wu                        DAG.getConstant(Offset, DL, MVT::i32));
11658ddc8169SZi Xuan Wu   return Addr;
11668ddc8169SZi Xuan Wu }
11678ddc8169SZi Xuan Wu 
11688ddc8169SZi Xuan Wu SDValue CSKYTargetLowering::LowerExternalSymbol(SDValue Op,
11698ddc8169SZi Xuan Wu                                                 SelectionDAG &DAG) const {
11708ddc8169SZi Xuan Wu   ExternalSymbolSDNode *N = cast<ExternalSymbolSDNode>(Op);
11718ddc8169SZi Xuan Wu 
11728ddc8169SZi Xuan Wu   return getAddr(N, DAG, false);
11738ddc8169SZi Xuan Wu }
11748ddc8169SZi Xuan Wu 
11758ddc8169SZi Xuan Wu SDValue CSKYTargetLowering::LowerJumpTable(SDValue Op,
11768ddc8169SZi Xuan Wu                                            SelectionDAG &DAG) const {
11778ddc8169SZi Xuan Wu   JumpTableSDNode *N = cast<JumpTableSDNode>(Op);
11788ddc8169SZi Xuan Wu 
11798ddc8169SZi Xuan Wu   return getAddr<JumpTableSDNode, false>(N, DAG);
11808ddc8169SZi Xuan Wu }
11818ddc8169SZi Xuan Wu 
11828ddc8169SZi Xuan Wu SDValue CSKYTargetLowering::LowerBlockAddress(SDValue Op,
11838ddc8169SZi Xuan Wu                                               SelectionDAG &DAG) const {
11848ddc8169SZi Xuan Wu   BlockAddressSDNode *N = cast<BlockAddressSDNode>(Op);
11858ddc8169SZi Xuan Wu 
11868ddc8169SZi Xuan Wu   return getAddr(N, DAG);
11878ddc8169SZi Xuan Wu }
11888ddc8169SZi Xuan Wu 
1189f4d61cdfSZi Xuan Wu (Zeson) SDValue CSKYTargetLowering::LowerConstantPool(SDValue Op,
1190f4d61cdfSZi Xuan Wu (Zeson)                                               SelectionDAG &DAG) const {
1191f4d61cdfSZi Xuan Wu (Zeson)   assert(!Subtarget.hasE2());
1192f4d61cdfSZi Xuan Wu (Zeson)   ConstantPoolSDNode *N = cast<ConstantPoolSDNode>(Op);
1193f4d61cdfSZi Xuan Wu (Zeson) 
1194f4d61cdfSZi Xuan Wu (Zeson)   return getAddr(N, DAG);
1195f4d61cdfSZi Xuan Wu (Zeson) }
1196f4d61cdfSZi Xuan Wu (Zeson) 
11978ddc8169SZi Xuan Wu SDValue CSKYTargetLowering::LowerVASTART(SDValue Op, SelectionDAG &DAG) const {
11988ddc8169SZi Xuan Wu   MachineFunction &MF = DAG.getMachineFunction();
11998ddc8169SZi Xuan Wu   CSKYMachineFunctionInfo *FuncInfo = MF.getInfo<CSKYMachineFunctionInfo>();
12008ddc8169SZi Xuan Wu 
12018ddc8169SZi Xuan Wu   SDLoc DL(Op);
12028ddc8169SZi Xuan Wu   SDValue FI = DAG.getFrameIndex(FuncInfo->getVarArgsFrameIndex(),
12038ddc8169SZi Xuan Wu                                  getPointerTy(MF.getDataLayout()));
12048ddc8169SZi Xuan Wu 
12058ddc8169SZi Xuan Wu   // vastart just stores the address of the VarArgsFrameIndex slot into the
12068ddc8169SZi Xuan Wu   // memory location argument.
12078ddc8169SZi Xuan Wu   const Value *SV = cast<SrcValueSDNode>(Op.getOperand(2))->getValue();
12088ddc8169SZi Xuan Wu   return DAG.getStore(Op.getOperand(0), DL, FI, Op.getOperand(1),
12098ddc8169SZi Xuan Wu                       MachinePointerInfo(SV));
12108ddc8169SZi Xuan Wu }
12118ddc8169SZi Xuan Wu 
12128ddc8169SZi Xuan Wu SDValue CSKYTargetLowering::LowerFRAMEADDR(SDValue Op,
12138ddc8169SZi Xuan Wu                                            SelectionDAG &DAG) const {
12148ddc8169SZi Xuan Wu   const CSKYRegisterInfo &RI = *Subtarget.getRegisterInfo();
12158ddc8169SZi Xuan Wu   MachineFunction &MF = DAG.getMachineFunction();
12168ddc8169SZi Xuan Wu   MachineFrameInfo &MFI = MF.getFrameInfo();
12178ddc8169SZi Xuan Wu   MFI.setFrameAddressIsTaken(true);
12188ddc8169SZi Xuan Wu 
12198ddc8169SZi Xuan Wu   EVT VT = Op.getValueType();
12208ddc8169SZi Xuan Wu   SDLoc dl(Op);
122180aeb622SAlex Bradbury   unsigned Depth = Op.getConstantOperandVal(0);
12228ddc8169SZi Xuan Wu   Register FrameReg = RI.getFrameRegister(MF);
12238ddc8169SZi Xuan Wu   SDValue FrameAddr = DAG.getCopyFromReg(DAG.getEntryNode(), dl, FrameReg, VT);
12248ddc8169SZi Xuan Wu   while (Depth--)
12258ddc8169SZi Xuan Wu     FrameAddr = DAG.getLoad(VT, dl, DAG.getEntryNode(), FrameAddr,
12268ddc8169SZi Xuan Wu                             MachinePointerInfo());
12278ddc8169SZi Xuan Wu   return FrameAddr;
12288ddc8169SZi Xuan Wu }
12298ddc8169SZi Xuan Wu 
12308ddc8169SZi Xuan Wu SDValue CSKYTargetLowering::LowerRETURNADDR(SDValue Op,
12318ddc8169SZi Xuan Wu                                             SelectionDAG &DAG) const {
12328ddc8169SZi Xuan Wu   const CSKYRegisterInfo &RI = *Subtarget.getRegisterInfo();
12338ddc8169SZi Xuan Wu   MachineFunction &MF = DAG.getMachineFunction();
12348ddc8169SZi Xuan Wu   MachineFrameInfo &MFI = MF.getFrameInfo();
12358ddc8169SZi Xuan Wu   MFI.setReturnAddressIsTaken(true);
12368ddc8169SZi Xuan Wu 
12378ddc8169SZi Xuan Wu   if (verifyReturnAddressArgumentIsConstant(Op, DAG))
12388ddc8169SZi Xuan Wu     return SDValue();
12398ddc8169SZi Xuan Wu 
12408ddc8169SZi Xuan Wu   EVT VT = Op.getValueType();
12418ddc8169SZi Xuan Wu   SDLoc dl(Op);
124280aeb622SAlex Bradbury   unsigned Depth = Op.getConstantOperandVal(0);
12438ddc8169SZi Xuan Wu   if (Depth) {
12448ddc8169SZi Xuan Wu     SDValue FrameAddr = LowerFRAMEADDR(Op, DAG);
12458ddc8169SZi Xuan Wu     SDValue Offset = DAG.getConstant(4, dl, MVT::i32);
12468ddc8169SZi Xuan Wu     return DAG.getLoad(VT, dl, DAG.getEntryNode(),
12478ddc8169SZi Xuan Wu                        DAG.getNode(ISD::ADD, dl, VT, FrameAddr, Offset),
12488ddc8169SZi Xuan Wu                        MachinePointerInfo());
12498ddc8169SZi Xuan Wu   }
12508ddc8169SZi Xuan Wu   // Return the value of the return address register, marking it an implicit
12518ddc8169SZi Xuan Wu   // live-in.
12528ddc8169SZi Xuan Wu   unsigned Reg = MF.addLiveIn(RI.getRARegister(), getRegClassFor(MVT::i32));
12538ddc8169SZi Xuan Wu   return DAG.getCopyFromReg(DAG.getEntryNode(), dl, Reg, VT);
12548ddc8169SZi Xuan Wu }
12558ddc8169SZi Xuan Wu 
12568ddc8169SZi Xuan Wu Register CSKYTargetLowering::getExceptionPointerRegister(
12578ddc8169SZi Xuan Wu     const Constant *PersonalityFn) const {
12588ddc8169SZi Xuan Wu   return CSKY::R0;
12598ddc8169SZi Xuan Wu }
12608ddc8169SZi Xuan Wu 
12618ddc8169SZi Xuan Wu Register CSKYTargetLowering::getExceptionSelectorRegister(
12628ddc8169SZi Xuan Wu     const Constant *PersonalityFn) const {
12638ddc8169SZi Xuan Wu   return CSKY::R1;
12648ddc8169SZi Xuan Wu }
126582bb8a58SZi Xuan Wu 
126682bb8a58SZi Xuan Wu SDValue CSKYTargetLowering::LowerGlobalTLSAddress(SDValue Op,
126782bb8a58SZi Xuan Wu                                                   SelectionDAG &DAG) const {
126882bb8a58SZi Xuan Wu   SDLoc DL(Op);
126982bb8a58SZi Xuan Wu   EVT Ty = Op.getValueType();
127082bb8a58SZi Xuan Wu   GlobalAddressSDNode *N = cast<GlobalAddressSDNode>(Op);
127182bb8a58SZi Xuan Wu   int64_t Offset = N->getOffset();
127282bb8a58SZi Xuan Wu   MVT XLenVT = MVT::i32;
127382bb8a58SZi Xuan Wu 
127482bb8a58SZi Xuan Wu   TLSModel::Model Model = getTargetMachine().getTLSModel(N->getGlobal());
127582bb8a58SZi Xuan Wu   SDValue Addr;
127682bb8a58SZi Xuan Wu   switch (Model) {
127782bb8a58SZi Xuan Wu   case TLSModel::LocalExec:
127882bb8a58SZi Xuan Wu     Addr = getStaticTLSAddr(N, DAG, /*UseGOT=*/false);
127982bb8a58SZi Xuan Wu     break;
128082bb8a58SZi Xuan Wu   case TLSModel::InitialExec:
128182bb8a58SZi Xuan Wu     Addr = getStaticTLSAddr(N, DAG, /*UseGOT=*/true);
128282bb8a58SZi Xuan Wu     break;
128382bb8a58SZi Xuan Wu   case TLSModel::LocalDynamic:
128482bb8a58SZi Xuan Wu   case TLSModel::GeneralDynamic:
128582bb8a58SZi Xuan Wu     Addr = getDynamicTLSAddr(N, DAG);
128682bb8a58SZi Xuan Wu     break;
128782bb8a58SZi Xuan Wu   }
128882bb8a58SZi Xuan Wu 
128982bb8a58SZi Xuan Wu   // In order to maximise the opportunity for common subexpression elimination,
129082bb8a58SZi Xuan Wu   // emit a separate ADD node for the global address offset instead of folding
129182bb8a58SZi Xuan Wu   // it in the global address node. Later peephole optimisations may choose to
129282bb8a58SZi Xuan Wu   // fold it back in when profitable.
129382bb8a58SZi Xuan Wu   if (Offset != 0)
129482bb8a58SZi Xuan Wu     return DAG.getNode(ISD::ADD, DL, Ty, Addr,
129582bb8a58SZi Xuan Wu                        DAG.getConstant(Offset, DL, XLenVT));
129682bb8a58SZi Xuan Wu   return Addr;
129782bb8a58SZi Xuan Wu }
129882bb8a58SZi Xuan Wu 
129982bb8a58SZi Xuan Wu SDValue CSKYTargetLowering::getStaticTLSAddr(GlobalAddressSDNode *N,
130082bb8a58SZi Xuan Wu                                              SelectionDAG &DAG,
130182bb8a58SZi Xuan Wu                                              bool UseGOT) const {
130282bb8a58SZi Xuan Wu   MachineFunction &MF = DAG.getMachineFunction();
130382bb8a58SZi Xuan Wu   CSKYMachineFunctionInfo *CFI = MF.getInfo<CSKYMachineFunctionInfo>();
130482bb8a58SZi Xuan Wu 
130582bb8a58SZi Xuan Wu   unsigned CSKYPCLabelIndex = CFI->createPICLabelUId();
130682bb8a58SZi Xuan Wu 
130782bb8a58SZi Xuan Wu   SDLoc DL(N);
130882bb8a58SZi Xuan Wu   EVT Ty = getPointerTy(DAG.getDataLayout());
130982bb8a58SZi Xuan Wu 
131082bb8a58SZi Xuan Wu   CSKYCP::CSKYCPModifier Flag = UseGOT ? CSKYCP::TLSIE : CSKYCP::TLSLE;
131182bb8a58SZi Xuan Wu   bool AddCurrentAddr = UseGOT ? true : false;
131282bb8a58SZi Xuan Wu   unsigned char PCAjust = UseGOT ? 4 : 0;
131382bb8a58SZi Xuan Wu 
131482bb8a58SZi Xuan Wu   CSKYConstantPoolValue *CPV =
131582bb8a58SZi Xuan Wu       CSKYConstantPoolConstant::Create(N->getGlobal(), CSKYCP::CPValue, PCAjust,
131682bb8a58SZi Xuan Wu                                        Flag, AddCurrentAddr, CSKYPCLabelIndex);
131782bb8a58SZi Xuan Wu   SDValue CAddr = DAG.getTargetConstantPool(CPV, Ty);
131882bb8a58SZi Xuan Wu 
131982bb8a58SZi Xuan Wu   SDValue Load;
132082bb8a58SZi Xuan Wu   if (UseGOT) {
132182bb8a58SZi Xuan Wu     SDValue PICLabel = DAG.getTargetConstant(CSKYPCLabelIndex, DL, MVT::i32);
132282bb8a58SZi Xuan Wu     auto *LRWGRS = DAG.getMachineNode(CSKY::PseudoTLSLA32, DL, {Ty, Ty},
132382bb8a58SZi Xuan Wu                                       {CAddr, PICLabel});
132482bb8a58SZi Xuan Wu     auto LRWADDGRS =
132582bb8a58SZi Xuan Wu         DAG.getNode(ISD::ADD, DL, Ty, SDValue(LRWGRS, 0), SDValue(LRWGRS, 1));
132682bb8a58SZi Xuan Wu     Load = DAG.getLoad(Ty, DL, DAG.getEntryNode(), LRWADDGRS,
132782bb8a58SZi Xuan Wu                        MachinePointerInfo(N->getGlobal()));
132882bb8a58SZi Xuan Wu   } else {
132982bb8a58SZi Xuan Wu     Load = SDValue(DAG.getMachineNode(CSKY::LRW32, DL, Ty, CAddr), 0);
133082bb8a58SZi Xuan Wu   }
133182bb8a58SZi Xuan Wu 
133282bb8a58SZi Xuan Wu   // Add the thread pointer.
133382bb8a58SZi Xuan Wu   SDValue TPReg = DAG.getRegister(CSKY::R31, MVT::i32);
133482bb8a58SZi Xuan Wu   return DAG.getNode(ISD::ADD, DL, Ty, Load, TPReg);
133582bb8a58SZi Xuan Wu }
133682bb8a58SZi Xuan Wu 
133782bb8a58SZi Xuan Wu SDValue CSKYTargetLowering::getDynamicTLSAddr(GlobalAddressSDNode *N,
133882bb8a58SZi Xuan Wu                                               SelectionDAG &DAG) const {
133982bb8a58SZi Xuan Wu   MachineFunction &MF = DAG.getMachineFunction();
134082bb8a58SZi Xuan Wu   CSKYMachineFunctionInfo *CFI = MF.getInfo<CSKYMachineFunctionInfo>();
134182bb8a58SZi Xuan Wu 
134282bb8a58SZi Xuan Wu   unsigned CSKYPCLabelIndex = CFI->createPICLabelUId();
134382bb8a58SZi Xuan Wu 
134482bb8a58SZi Xuan Wu   SDLoc DL(N);
134582bb8a58SZi Xuan Wu   EVT Ty = getPointerTy(DAG.getDataLayout());
134682bb8a58SZi Xuan Wu   IntegerType *CallTy = Type::getIntNTy(*DAG.getContext(), Ty.getSizeInBits());
134782bb8a58SZi Xuan Wu 
134882bb8a58SZi Xuan Wu   CSKYConstantPoolValue *CPV =
134982bb8a58SZi Xuan Wu       CSKYConstantPoolConstant::Create(N->getGlobal(), CSKYCP::CPValue, 4,
135082bb8a58SZi Xuan Wu                                        CSKYCP::TLSGD, true, CSKYPCLabelIndex);
135182bb8a58SZi Xuan Wu   SDValue Addr = DAG.getTargetConstantPool(CPV, Ty);
135282bb8a58SZi Xuan Wu   SDValue PICLabel = DAG.getTargetConstant(CSKYPCLabelIndex, DL, MVT::i32);
135382bb8a58SZi Xuan Wu 
135482bb8a58SZi Xuan Wu   auto *LRWGRS =
135582bb8a58SZi Xuan Wu       DAG.getMachineNode(CSKY::PseudoTLSLA32, DL, {Ty, Ty}, {Addr, PICLabel});
135682bb8a58SZi Xuan Wu 
135782bb8a58SZi Xuan Wu   auto Load =
135882bb8a58SZi Xuan Wu       DAG.getNode(ISD::ADD, DL, Ty, SDValue(LRWGRS, 0), SDValue(LRWGRS, 1));
135982bb8a58SZi Xuan Wu 
136082bb8a58SZi Xuan Wu   // Prepare argument list to generate call.
136182bb8a58SZi Xuan Wu   ArgListTy Args;
136282bb8a58SZi Xuan Wu   ArgListEntry Entry;
136382bb8a58SZi Xuan Wu   Entry.Node = Load;
136482bb8a58SZi Xuan Wu   Entry.Ty = CallTy;
136582bb8a58SZi Xuan Wu   Args.push_back(Entry);
136682bb8a58SZi Xuan Wu 
136782bb8a58SZi Xuan Wu   // Setup call to __tls_get_addr.
136882bb8a58SZi Xuan Wu   TargetLowering::CallLoweringInfo CLI(DAG);
136982bb8a58SZi Xuan Wu   CLI.setDebugLoc(DL)
137082bb8a58SZi Xuan Wu       .setChain(DAG.getEntryNode())
137182bb8a58SZi Xuan Wu       .setLibCallee(CallingConv::C, CallTy,
137282bb8a58SZi Xuan Wu                     DAG.getExternalSymbol("__tls_get_addr", Ty),
137382bb8a58SZi Xuan Wu                     std::move(Args));
137482bb8a58SZi Xuan Wu   SDValue V = LowerCallTo(CLI).first;
137582bb8a58SZi Xuan Wu 
137682bb8a58SZi Xuan Wu   return V;
137782bb8a58SZi Xuan Wu }
13786d05f3f5SBen Shi 
13796d05f3f5SBen Shi bool CSKYTargetLowering::decomposeMulByConstant(LLVMContext &Context, EVT VT,
13806d05f3f5SBen Shi                                                 SDValue C) const {
13816d05f3f5SBen Shi   if (!VT.isScalarInteger())
13826d05f3f5SBen Shi     return false;
13836d05f3f5SBen Shi 
13846d05f3f5SBen Shi   // Omit if data size exceeds.
13856d05f3f5SBen Shi   if (VT.getSizeInBits() > Subtarget.XLen)
13866d05f3f5SBen Shi     return false;
13876d05f3f5SBen Shi 
13886d05f3f5SBen Shi   if (auto *ConstNode = dyn_cast<ConstantSDNode>(C.getNode())) {
13896d05f3f5SBen Shi     const APInt &Imm = ConstNode->getAPIntValue();
13906d05f3f5SBen Shi     // Break MULT to LSLI + ADDU/SUBU.
13916d05f3f5SBen Shi     if ((Imm + 1).isPowerOf2() || (Imm - 1).isPowerOf2() ||
13926d05f3f5SBen Shi         (1 - Imm).isPowerOf2())
13936d05f3f5SBen Shi       return true;
13946d05f3f5SBen Shi     // Only break MULT for sub targets without MULT32, since an extra
13956d05f3f5SBen Shi     // instruction will be generated against the above 3 cases. We leave it
13966d05f3f5SBen Shi     // unchanged on sub targets with MULT32, since not sure it is better.
13976d05f3f5SBen Shi     if (!Subtarget.hasE2() && (-1 - Imm).isPowerOf2())
13986d05f3f5SBen Shi       return true;
139957c6fe27SBen Shi     // Break (MULT x, imm) to ([IXH32|IXW32|IXD32] (LSLI32 x, i0), x) when
140057c6fe27SBen Shi     // imm=(1<<i0)+[2|4|8] and imm has to be composed via a MOVIH32/ORI32 pair.
140157c6fe27SBen Shi     if (Imm.ugt(0xffff) && ((Imm - 2).isPowerOf2() || (Imm - 4).isPowerOf2()) &&
140257c6fe27SBen Shi         Subtarget.hasE2())
140357c6fe27SBen Shi       return true;
140457c6fe27SBen Shi     if (Imm.ugt(0xffff) && (Imm - 8).isPowerOf2() && Subtarget.has2E3())
140557c6fe27SBen Shi       return true;
14066d05f3f5SBen Shi   }
14076d05f3f5SBen Shi 
14086d05f3f5SBen Shi   return false;
14096d05f3f5SBen Shi }
141075c3c6acSBen Shi 
141175c3c6acSBen Shi bool CSKYTargetLowering::isCheapToSpeculateCttz(Type *Ty) const {
141275c3c6acSBen Shi   return Subtarget.has2E3();
141375c3c6acSBen Shi }
141475c3c6acSBen Shi 
141575c3c6acSBen Shi bool CSKYTargetLowering::isCheapToSpeculateCtlz(Type *Ty) const {
141675c3c6acSBen Shi   return Subtarget.hasE2();
141775c3c6acSBen Shi }
1418