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"
2281ad6265SDimitry 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
CSKYTargetLowering(const TargetMachine & TM,const CSKYSubtarget & STI)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
5406c3fb27SDimitry Andric setOperationAction(ISD::UADDO_CARRY, MVT::i32, Legal);
5506c3fb27SDimitry Andric setOperationAction(ISD::USUBO_CARRY, 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::CTPOP, MVT::i32, Expand);
630eae32dcSDimitry Andric setOperationAction(ISD::ROTR, MVT::i32, Expand);
640eae32dcSDimitry Andric setOperationAction(ISD::SHL_PARTS, MVT::i32, Expand);
650eae32dcSDimitry Andric setOperationAction(ISD::SRL_PARTS, MVT::i32, Expand);
660eae32dcSDimitry Andric setOperationAction(ISD::SRA_PARTS, MVT::i32, Expand);
670eae32dcSDimitry Andric setOperationAction(ISD::UMUL_LOHI, MVT::i32, Expand);
680eae32dcSDimitry Andric setOperationAction(ISD::SMUL_LOHI, MVT::i32, Expand);
6904eeddc0SDimitry Andric setOperationAction(ISD::SELECT_CC, MVT::i32, Expand);
7004eeddc0SDimitry Andric setOperationAction(ISD::BR_CC, MVT::i32, Expand);
7104eeddc0SDimitry Andric setOperationAction(ISD::BR_JT, MVT::Other, Expand);
720eae32dcSDimitry Andric setOperationAction(ISD::DYNAMIC_STACKALLOC, MVT::i32, Expand);
730eae32dcSDimitry Andric setOperationAction(ISD::STACKSAVE, MVT::Other, Expand);
740eae32dcSDimitry Andric setOperationAction(ISD::STACKRESTORE, MVT::Other, Expand);
750eae32dcSDimitry Andric setOperationAction(ISD::MULHS, MVT::i32, Expand);
760eae32dcSDimitry Andric setOperationAction(ISD::MULHU, MVT::i32, Expand);
7704eeddc0SDimitry Andric setOperationAction(ISD::VAARG, MVT::Other, Expand);
7804eeddc0SDimitry Andric setOperationAction(ISD::VACOPY, MVT::Other, Expand);
7904eeddc0SDimitry Andric setOperationAction(ISD::VAEND, MVT::Other, Expand);
800eae32dcSDimitry Andric
810eae32dcSDimitry Andric setLoadExtAction(ISD::EXTLOAD, MVT::i32, MVT::i1, Promote);
820eae32dcSDimitry Andric setLoadExtAction(ISD::SEXTLOAD, MVT::i32, MVT::i1, Promote);
830eae32dcSDimitry Andric setLoadExtAction(ISD::ZEXTLOAD, MVT::i32, MVT::i1, Promote);
840eae32dcSDimitry Andric
8504eeddc0SDimitry Andric setOperationAction(ISD::GlobalAddress, MVT::i32, Custom);
8604eeddc0SDimitry Andric setOperationAction(ISD::ExternalSymbol, MVT::i32, Custom);
8704eeddc0SDimitry Andric setOperationAction(ISD::GlobalTLSAddress, MVT::i32, Custom);
8804eeddc0SDimitry Andric setOperationAction(ISD::BlockAddress, MVT::i32, Custom);
89bdd1243dSDimitry Andric if (!Subtarget.hasE2()) {
90bdd1243dSDimitry Andric setOperationAction(ISD::ConstantPool, MVT::i32, Custom);
91bdd1243dSDimitry Andric }
9204eeddc0SDimitry Andric setOperationAction(ISD::JumpTable, MVT::i32, Custom);
9304eeddc0SDimitry Andric setOperationAction(ISD::VASTART, MVT::Other, Custom);
9404eeddc0SDimitry Andric
950eae32dcSDimitry Andric if (!Subtarget.hasE2()) {
960eae32dcSDimitry Andric setLoadExtAction(ISD::SEXTLOAD, MVT::i32, MVT::i8, Expand);
970eae32dcSDimitry Andric setLoadExtAction(ISD::SEXTLOAD, MVT::i32, MVT::i16, Expand);
980eae32dcSDimitry Andric setOperationAction(ISD::CTLZ, MVT::i32, Expand);
990eae32dcSDimitry Andric setOperationAction(ISD::BSWAP, MVT::i32, Expand);
1000eae32dcSDimitry Andric }
1010eae32dcSDimitry Andric
1020eae32dcSDimitry Andric if (!Subtarget.has2E3()) {
1030eae32dcSDimitry Andric setOperationAction(ISD::ABS, MVT::i32, Expand);
1040eae32dcSDimitry Andric setOperationAction(ISD::BITREVERSE, MVT::i32, Expand);
1055f757f3fSDimitry Andric setOperationAction(ISD::CTTZ, MVT::i32, Expand);
1060eae32dcSDimitry Andric setOperationAction(ISD::SDIV, MVT::i32, Expand);
1070eae32dcSDimitry Andric setOperationAction(ISD::UDIV, MVT::i32, Expand);
1080eae32dcSDimitry Andric }
1090eae32dcSDimitry Andric
11004eeddc0SDimitry Andric setOperationAction(ISD::ATOMIC_FENCE, MVT::Other, Expand);
11104eeddc0SDimitry Andric
11204eeddc0SDimitry Andric // Float
11304eeddc0SDimitry Andric
11404eeddc0SDimitry Andric ISD::CondCode FPCCToExtend[] = {
11504eeddc0SDimitry Andric ISD::SETONE, ISD::SETUEQ, ISD::SETUGT,
11604eeddc0SDimitry Andric ISD::SETUGE, ISD::SETULT, ISD::SETULE,
11704eeddc0SDimitry Andric };
11804eeddc0SDimitry Andric
11906c3fb27SDimitry Andric ISD::NodeType FPOpToExpand[] = {
12006c3fb27SDimitry Andric ISD::FSIN, ISD::FCOS, ISD::FSINCOS, ISD::FPOW,
12106c3fb27SDimitry Andric ISD::FREM, ISD::FCOPYSIGN, ISD::FP16_TO_FP, ISD::FP_TO_FP16};
12204eeddc0SDimitry Andric
12304eeddc0SDimitry Andric if (STI.useHardFloat()) {
12404eeddc0SDimitry Andric
12504eeddc0SDimitry Andric MVT AllVTy[] = {MVT::f32, MVT::f64};
12604eeddc0SDimitry Andric
12704eeddc0SDimitry Andric for (auto VT : AllVTy) {
12804eeddc0SDimitry Andric setOperationAction(ISD::FREM, VT, Expand);
12904eeddc0SDimitry Andric setOperationAction(ISD::SELECT_CC, VT, Expand);
13004eeddc0SDimitry Andric setOperationAction(ISD::BR_CC, VT, Expand);
13104eeddc0SDimitry Andric
13204eeddc0SDimitry Andric for (auto CC : FPCCToExtend)
13304eeddc0SDimitry Andric setCondCodeAction(CC, VT, Expand);
13404eeddc0SDimitry Andric for (auto Op : FPOpToExpand)
13504eeddc0SDimitry Andric setOperationAction(Op, VT, Expand);
13604eeddc0SDimitry Andric }
13704eeddc0SDimitry Andric
13804eeddc0SDimitry Andric if (STI.hasFPUv2SingleFloat() || STI.hasFPUv3SingleFloat()) {
13904eeddc0SDimitry Andric setOperationAction(ISD::ConstantFP, MVT::f32, Legal);
14006c3fb27SDimitry Andric setLoadExtAction(ISD::EXTLOAD, MVT::f32, MVT::f16, Expand);
14106c3fb27SDimitry Andric setTruncStoreAction(MVT::f32, MVT::f16, Expand);
14204eeddc0SDimitry Andric }
14304eeddc0SDimitry Andric if (STI.hasFPUv2DoubleFloat() || STI.hasFPUv3DoubleFloat()) {
14404eeddc0SDimitry Andric setLoadExtAction(ISD::EXTLOAD, MVT::f64, MVT::f32, Expand);
14504eeddc0SDimitry Andric setTruncStoreAction(MVT::f64, MVT::f32, Expand);
14606c3fb27SDimitry Andric setLoadExtAction(ISD::EXTLOAD, MVT::f64, MVT::f16, Expand);
14706c3fb27SDimitry Andric setTruncStoreAction(MVT::f64, MVT::f16, Expand);
14804eeddc0SDimitry Andric }
14904eeddc0SDimitry Andric }
15004eeddc0SDimitry Andric
151349cc55cSDimitry Andric // Compute derived properties from the register classes.
152349cc55cSDimitry Andric computeRegisterProperties(STI.getRegisterInfo());
153349cc55cSDimitry Andric
154349cc55cSDimitry Andric setBooleanContents(UndefinedBooleanContent);
155349cc55cSDimitry Andric setBooleanVectorContents(ZeroOrNegativeOneBooleanContent);
156349cc55cSDimitry Andric
157349cc55cSDimitry Andric // TODO: Add atomic support fully.
158349cc55cSDimitry Andric setMaxAtomicSizeInBitsSupported(0);
159349cc55cSDimitry Andric
160349cc55cSDimitry Andric setStackPointerRegisterToSaveRestore(CSKY::R14);
16106c3fb27SDimitry Andric setMinFunctionAlignment(Align(2));
162349cc55cSDimitry Andric setSchedulingPreference(Sched::Source);
163349cc55cSDimitry Andric }
164349cc55cSDimitry Andric
LowerOperation(SDValue Op,SelectionDAG & DAG) const16504eeddc0SDimitry Andric SDValue CSKYTargetLowering::LowerOperation(SDValue Op,
16604eeddc0SDimitry Andric SelectionDAG &DAG) const {
16704eeddc0SDimitry Andric switch (Op.getOpcode()) {
16804eeddc0SDimitry Andric default:
16904eeddc0SDimitry Andric llvm_unreachable("unimplemented op");
17004eeddc0SDimitry Andric case ISD::GlobalAddress:
17104eeddc0SDimitry Andric return LowerGlobalAddress(Op, DAG);
17204eeddc0SDimitry Andric case ISD::ExternalSymbol:
17304eeddc0SDimitry Andric return LowerExternalSymbol(Op, DAG);
17404eeddc0SDimitry Andric case ISD::GlobalTLSAddress:
17504eeddc0SDimitry Andric return LowerGlobalTLSAddress(Op, DAG);
17604eeddc0SDimitry Andric case ISD::JumpTable:
17704eeddc0SDimitry Andric return LowerJumpTable(Op, DAG);
17804eeddc0SDimitry Andric case ISD::BlockAddress:
17904eeddc0SDimitry Andric return LowerBlockAddress(Op, DAG);
180bdd1243dSDimitry Andric case ISD::ConstantPool:
181bdd1243dSDimitry Andric return LowerConstantPool(Op, DAG);
18204eeddc0SDimitry Andric case ISD::VASTART:
18304eeddc0SDimitry Andric return LowerVASTART(Op, DAG);
18404eeddc0SDimitry Andric case ISD::FRAMEADDR:
18504eeddc0SDimitry Andric return LowerFRAMEADDR(Op, DAG);
18604eeddc0SDimitry Andric case ISD::RETURNADDR:
18704eeddc0SDimitry Andric return LowerRETURNADDR(Op, DAG);
18804eeddc0SDimitry Andric }
18904eeddc0SDimitry Andric }
19004eeddc0SDimitry Andric
getSetCCResultType(const DataLayout & DL,LLVMContext & Context,EVT VT) const191349cc55cSDimitry Andric EVT CSKYTargetLowering::getSetCCResultType(const DataLayout &DL,
192349cc55cSDimitry Andric LLVMContext &Context, EVT VT) const {
193349cc55cSDimitry Andric if (!VT.isVector())
194349cc55cSDimitry Andric return MVT::i32;
195349cc55cSDimitry Andric
196349cc55cSDimitry Andric return VT.changeVectorElementTypeToInteger();
197349cc55cSDimitry Andric }
198349cc55cSDimitry Andric
convertValVTToLocVT(SelectionDAG & DAG,SDValue Val,const CCValAssign & VA,const SDLoc & DL)199349cc55cSDimitry Andric static SDValue convertValVTToLocVT(SelectionDAG &DAG, SDValue Val,
200349cc55cSDimitry Andric const CCValAssign &VA, const SDLoc &DL) {
201349cc55cSDimitry Andric EVT LocVT = VA.getLocVT();
202349cc55cSDimitry Andric
203349cc55cSDimitry Andric switch (VA.getLocInfo()) {
204349cc55cSDimitry Andric default:
205349cc55cSDimitry Andric llvm_unreachable("Unexpected CCValAssign::LocInfo");
206349cc55cSDimitry Andric case CCValAssign::Full:
207349cc55cSDimitry Andric break;
208349cc55cSDimitry Andric case CCValAssign::BCvt:
209349cc55cSDimitry Andric Val = DAG.getNode(ISD::BITCAST, DL, LocVT, Val);
210349cc55cSDimitry Andric break;
211349cc55cSDimitry Andric }
212349cc55cSDimitry Andric return Val;
213349cc55cSDimitry Andric }
214349cc55cSDimitry Andric
convertLocVTToValVT(SelectionDAG & DAG,SDValue Val,const CCValAssign & VA,const SDLoc & DL)215349cc55cSDimitry Andric static SDValue convertLocVTToValVT(SelectionDAG &DAG, SDValue Val,
216349cc55cSDimitry Andric const CCValAssign &VA, const SDLoc &DL) {
217349cc55cSDimitry Andric switch (VA.getLocInfo()) {
218349cc55cSDimitry Andric default:
219349cc55cSDimitry Andric llvm_unreachable("Unexpected CCValAssign::LocInfo");
220349cc55cSDimitry Andric case CCValAssign::Full:
221349cc55cSDimitry Andric break;
222349cc55cSDimitry Andric case CCValAssign::BCvt:
223349cc55cSDimitry Andric Val = DAG.getNode(ISD::BITCAST, DL, VA.getValVT(), Val);
224349cc55cSDimitry Andric break;
225349cc55cSDimitry Andric }
226349cc55cSDimitry Andric return Val;
227349cc55cSDimitry Andric }
228349cc55cSDimitry Andric
unpackFromRegLoc(const CSKYSubtarget & Subtarget,SelectionDAG & DAG,SDValue Chain,const CCValAssign & VA,const SDLoc & DL)229349cc55cSDimitry Andric static SDValue unpackFromRegLoc(const CSKYSubtarget &Subtarget,
230349cc55cSDimitry Andric SelectionDAG &DAG, SDValue Chain,
231349cc55cSDimitry Andric const CCValAssign &VA, const SDLoc &DL) {
232349cc55cSDimitry Andric MachineFunction &MF = DAG.getMachineFunction();
233349cc55cSDimitry Andric MachineRegisterInfo &RegInfo = MF.getRegInfo();
234349cc55cSDimitry Andric EVT LocVT = VA.getLocVT();
235349cc55cSDimitry Andric SDValue Val;
236349cc55cSDimitry Andric const TargetRegisterClass *RC;
237349cc55cSDimitry Andric
238349cc55cSDimitry Andric switch (LocVT.getSimpleVT().SimpleTy) {
239349cc55cSDimitry Andric default:
240349cc55cSDimitry Andric llvm_unreachable("Unexpected register type");
241349cc55cSDimitry Andric case MVT::i32:
242349cc55cSDimitry Andric RC = &CSKY::GPRRegClass;
243349cc55cSDimitry Andric break;
24404eeddc0SDimitry Andric case MVT::f32:
24504eeddc0SDimitry Andric RC = Subtarget.hasFPUv2SingleFloat() ? &CSKY::sFPR32RegClass
24604eeddc0SDimitry Andric : &CSKY::FPR32RegClass;
24704eeddc0SDimitry Andric break;
24804eeddc0SDimitry Andric case MVT::f64:
24904eeddc0SDimitry Andric RC = Subtarget.hasFPUv2DoubleFloat() ? &CSKY::sFPR64RegClass
25004eeddc0SDimitry Andric : &CSKY::FPR64RegClass;
25104eeddc0SDimitry Andric break;
252349cc55cSDimitry Andric }
253349cc55cSDimitry Andric
254349cc55cSDimitry Andric Register VReg = RegInfo.createVirtualRegister(RC);
255349cc55cSDimitry Andric RegInfo.addLiveIn(VA.getLocReg(), VReg);
256349cc55cSDimitry Andric Val = DAG.getCopyFromReg(Chain, DL, VReg, LocVT);
257349cc55cSDimitry Andric
258349cc55cSDimitry Andric return convertLocVTToValVT(DAG, Val, VA, DL);
259349cc55cSDimitry Andric }
260349cc55cSDimitry Andric
unpackFromMemLoc(SelectionDAG & DAG,SDValue Chain,const CCValAssign & VA,const SDLoc & DL)261349cc55cSDimitry Andric static SDValue unpackFromMemLoc(SelectionDAG &DAG, SDValue Chain,
262349cc55cSDimitry Andric const CCValAssign &VA, const SDLoc &DL) {
263349cc55cSDimitry Andric MachineFunction &MF = DAG.getMachineFunction();
264349cc55cSDimitry Andric MachineFrameInfo &MFI = MF.getFrameInfo();
265349cc55cSDimitry Andric EVT LocVT = VA.getLocVT();
266349cc55cSDimitry Andric EVT ValVT = VA.getValVT();
267349cc55cSDimitry Andric EVT PtrVT = MVT::getIntegerVT(DAG.getDataLayout().getPointerSizeInBits(0));
268349cc55cSDimitry Andric int FI = MFI.CreateFixedObject(ValVT.getSizeInBits() / 8,
269349cc55cSDimitry Andric VA.getLocMemOffset(), /*Immutable=*/true);
270349cc55cSDimitry Andric SDValue FIN = DAG.getFrameIndex(FI, PtrVT);
271349cc55cSDimitry Andric SDValue Val;
272349cc55cSDimitry Andric
273349cc55cSDimitry Andric ISD::LoadExtType ExtType;
274349cc55cSDimitry Andric switch (VA.getLocInfo()) {
275349cc55cSDimitry Andric default:
276349cc55cSDimitry Andric llvm_unreachable("Unexpected CCValAssign::LocInfo");
277349cc55cSDimitry Andric case CCValAssign::Full:
278349cc55cSDimitry Andric case CCValAssign::BCvt:
279349cc55cSDimitry Andric ExtType = ISD::NON_EXTLOAD;
280349cc55cSDimitry Andric break;
281349cc55cSDimitry Andric }
282349cc55cSDimitry Andric Val = DAG.getExtLoad(
283349cc55cSDimitry Andric ExtType, DL, LocVT, Chain, FIN,
284349cc55cSDimitry Andric MachinePointerInfo::getFixedStack(DAG.getMachineFunction(), FI), ValVT);
285349cc55cSDimitry Andric return Val;
286349cc55cSDimitry Andric }
287349cc55cSDimitry Andric
unpack64(SelectionDAG & DAG,SDValue Chain,const CCValAssign & VA,const SDLoc & DL)28804eeddc0SDimitry Andric static SDValue unpack64(SelectionDAG &DAG, SDValue Chain, const CCValAssign &VA,
28904eeddc0SDimitry Andric const SDLoc &DL) {
29004eeddc0SDimitry Andric assert(VA.getLocVT() == MVT::i32 &&
29104eeddc0SDimitry Andric (VA.getValVT() == MVT::f64 || VA.getValVT() == MVT::i64) &&
29204eeddc0SDimitry Andric "Unexpected VA");
29304eeddc0SDimitry Andric MachineFunction &MF = DAG.getMachineFunction();
29404eeddc0SDimitry Andric MachineFrameInfo &MFI = MF.getFrameInfo();
29504eeddc0SDimitry Andric MachineRegisterInfo &RegInfo = MF.getRegInfo();
29604eeddc0SDimitry Andric
29704eeddc0SDimitry Andric if (VA.isMemLoc()) {
29804eeddc0SDimitry Andric // f64/i64 is passed on the stack.
29904eeddc0SDimitry Andric int FI = MFI.CreateFixedObject(8, VA.getLocMemOffset(), /*Immutable=*/true);
30004eeddc0SDimitry Andric SDValue FIN = DAG.getFrameIndex(FI, MVT::i32);
30104eeddc0SDimitry Andric return DAG.getLoad(VA.getValVT(), DL, Chain, FIN,
30204eeddc0SDimitry Andric MachinePointerInfo::getFixedStack(MF, FI));
30304eeddc0SDimitry Andric }
30404eeddc0SDimitry Andric
30504eeddc0SDimitry Andric assert(VA.isRegLoc() && "Expected register VA assignment");
30604eeddc0SDimitry Andric
30704eeddc0SDimitry Andric Register LoVReg = RegInfo.createVirtualRegister(&CSKY::GPRRegClass);
30804eeddc0SDimitry Andric RegInfo.addLiveIn(VA.getLocReg(), LoVReg);
30904eeddc0SDimitry Andric SDValue Lo = DAG.getCopyFromReg(Chain, DL, LoVReg, MVT::i32);
31004eeddc0SDimitry Andric SDValue Hi;
31104eeddc0SDimitry Andric if (VA.getLocReg() == CSKY::R3) {
31204eeddc0SDimitry Andric // Second half of f64/i64 is passed on the stack.
31304eeddc0SDimitry Andric int FI = MFI.CreateFixedObject(4, 0, /*Immutable=*/true);
31404eeddc0SDimitry Andric SDValue FIN = DAG.getFrameIndex(FI, MVT::i32);
31504eeddc0SDimitry Andric Hi = DAG.getLoad(MVT::i32, DL, Chain, FIN,
31604eeddc0SDimitry Andric MachinePointerInfo::getFixedStack(MF, FI));
31704eeddc0SDimitry Andric } else {
31804eeddc0SDimitry Andric // Second half of f64/i64 is passed in another GPR.
31904eeddc0SDimitry Andric Register HiVReg = RegInfo.createVirtualRegister(&CSKY::GPRRegClass);
32004eeddc0SDimitry Andric RegInfo.addLiveIn(VA.getLocReg() + 1, HiVReg);
32104eeddc0SDimitry Andric Hi = DAG.getCopyFromReg(Chain, DL, HiVReg, MVT::i32);
32204eeddc0SDimitry Andric }
32304eeddc0SDimitry Andric return DAG.getNode(CSKYISD::BITCAST_FROM_LOHI, DL, VA.getValVT(), Lo, Hi);
32404eeddc0SDimitry Andric }
32504eeddc0SDimitry Andric
326349cc55cSDimitry Andric // Transform physical registers into virtual registers.
LowerFormalArguments(SDValue Chain,CallingConv::ID CallConv,bool IsVarArg,const SmallVectorImpl<ISD::InputArg> & Ins,const SDLoc & DL,SelectionDAG & DAG,SmallVectorImpl<SDValue> & InVals) const327349cc55cSDimitry Andric SDValue CSKYTargetLowering::LowerFormalArguments(
328349cc55cSDimitry Andric SDValue Chain, CallingConv::ID CallConv, bool IsVarArg,
329349cc55cSDimitry Andric const SmallVectorImpl<ISD::InputArg> &Ins, const SDLoc &DL,
330349cc55cSDimitry Andric SelectionDAG &DAG, SmallVectorImpl<SDValue> &InVals) const {
331349cc55cSDimitry Andric
332349cc55cSDimitry Andric switch (CallConv) {
333349cc55cSDimitry Andric default:
334349cc55cSDimitry Andric report_fatal_error("Unsupported calling convention");
335349cc55cSDimitry Andric case CallingConv::C:
336349cc55cSDimitry Andric case CallingConv::Fast:
337349cc55cSDimitry Andric break;
338349cc55cSDimitry Andric }
339349cc55cSDimitry Andric
340349cc55cSDimitry Andric MachineFunction &MF = DAG.getMachineFunction();
341349cc55cSDimitry Andric
342349cc55cSDimitry Andric // Used with vargs to acumulate store chains.
343349cc55cSDimitry Andric std::vector<SDValue> OutChains;
344349cc55cSDimitry Andric
345349cc55cSDimitry Andric // Assign locations to all of the incoming arguments.
346349cc55cSDimitry Andric SmallVector<CCValAssign, 16> ArgLocs;
347349cc55cSDimitry Andric CCState CCInfo(CallConv, IsVarArg, MF, ArgLocs, *DAG.getContext());
348349cc55cSDimitry Andric
349349cc55cSDimitry Andric CCInfo.AnalyzeFormalArguments(Ins, CCAssignFnForCall(CallConv, IsVarArg));
350349cc55cSDimitry Andric
351349cc55cSDimitry Andric for (unsigned i = 0, e = ArgLocs.size(); i != e; ++i) {
352349cc55cSDimitry Andric CCValAssign &VA = ArgLocs[i];
353349cc55cSDimitry Andric SDValue ArgValue;
354349cc55cSDimitry Andric
35504eeddc0SDimitry Andric bool IsF64OnCSKY = VA.getLocVT() == MVT::i32 && VA.getValVT() == MVT::f64;
35604eeddc0SDimitry Andric
35704eeddc0SDimitry Andric if (IsF64OnCSKY)
35804eeddc0SDimitry Andric ArgValue = unpack64(DAG, Chain, VA, DL);
35904eeddc0SDimitry Andric else if (VA.isRegLoc())
360349cc55cSDimitry Andric ArgValue = unpackFromRegLoc(Subtarget, DAG, Chain, VA, DL);
361349cc55cSDimitry Andric else
362349cc55cSDimitry Andric ArgValue = unpackFromMemLoc(DAG, Chain, VA, DL);
363349cc55cSDimitry Andric
364349cc55cSDimitry Andric InVals.push_back(ArgValue);
365349cc55cSDimitry Andric }
366349cc55cSDimitry Andric
367349cc55cSDimitry Andric if (IsVarArg) {
368349cc55cSDimitry Andric const unsigned XLenInBytes = 4;
369349cc55cSDimitry Andric const MVT XLenVT = MVT::i32;
370349cc55cSDimitry Andric
371bdd1243dSDimitry Andric ArrayRef<MCPhysReg> ArgRegs = ArrayRef(GPRArgRegs);
372349cc55cSDimitry Andric unsigned Idx = CCInfo.getFirstUnallocated(ArgRegs);
373349cc55cSDimitry Andric const TargetRegisterClass *RC = &CSKY::GPRRegClass;
374349cc55cSDimitry Andric MachineFrameInfo &MFI = MF.getFrameInfo();
375349cc55cSDimitry Andric MachineRegisterInfo &RegInfo = MF.getRegInfo();
376349cc55cSDimitry Andric CSKYMachineFunctionInfo *CSKYFI = MF.getInfo<CSKYMachineFunctionInfo>();
377349cc55cSDimitry Andric
378349cc55cSDimitry Andric // Offset of the first variable argument from stack pointer, and size of
379349cc55cSDimitry Andric // the vararg save area. For now, the varargs save area is either zero or
380349cc55cSDimitry Andric // large enough to hold a0-a4.
381349cc55cSDimitry Andric int VaArgOffset, VarArgsSaveSize;
382349cc55cSDimitry Andric
383349cc55cSDimitry Andric // If all registers are allocated, then all varargs must be passed on the
384349cc55cSDimitry Andric // stack and we don't need to save any argregs.
385349cc55cSDimitry Andric if (ArgRegs.size() == Idx) {
38606c3fb27SDimitry Andric VaArgOffset = CCInfo.getStackSize();
387349cc55cSDimitry Andric VarArgsSaveSize = 0;
388349cc55cSDimitry Andric } else {
389349cc55cSDimitry Andric VarArgsSaveSize = XLenInBytes * (ArgRegs.size() - Idx);
390349cc55cSDimitry Andric VaArgOffset = -VarArgsSaveSize;
391349cc55cSDimitry Andric }
392349cc55cSDimitry Andric
393349cc55cSDimitry Andric // Record the frame index of the first variable argument
394349cc55cSDimitry Andric // which is a value necessary to VASTART.
395349cc55cSDimitry Andric int FI = MFI.CreateFixedObject(XLenInBytes, VaArgOffset, true);
396349cc55cSDimitry Andric CSKYFI->setVarArgsFrameIndex(FI);
397349cc55cSDimitry Andric
398349cc55cSDimitry Andric // Copy the integer registers that may have been used for passing varargs
399349cc55cSDimitry Andric // to the vararg save area.
400349cc55cSDimitry Andric for (unsigned I = Idx; I < ArgRegs.size();
401349cc55cSDimitry Andric ++I, VaArgOffset += XLenInBytes) {
402349cc55cSDimitry Andric const Register Reg = RegInfo.createVirtualRegister(RC);
403349cc55cSDimitry Andric RegInfo.addLiveIn(ArgRegs[I], Reg);
404349cc55cSDimitry Andric SDValue ArgValue = DAG.getCopyFromReg(Chain, DL, Reg, XLenVT);
405349cc55cSDimitry Andric FI = MFI.CreateFixedObject(XLenInBytes, VaArgOffset, true);
406349cc55cSDimitry Andric SDValue PtrOff = DAG.getFrameIndex(FI, getPointerTy(DAG.getDataLayout()));
407349cc55cSDimitry Andric SDValue Store = DAG.getStore(Chain, DL, ArgValue, PtrOff,
408349cc55cSDimitry Andric MachinePointerInfo::getFixedStack(MF, FI));
409349cc55cSDimitry Andric cast<StoreSDNode>(Store.getNode())
410349cc55cSDimitry Andric ->getMemOperand()
411349cc55cSDimitry Andric ->setValue((Value *)nullptr);
412349cc55cSDimitry Andric OutChains.push_back(Store);
413349cc55cSDimitry Andric }
414349cc55cSDimitry Andric CSKYFI->setVarArgsSaveSize(VarArgsSaveSize);
415349cc55cSDimitry Andric }
416349cc55cSDimitry Andric
417349cc55cSDimitry Andric // All stores are grouped in one node to allow the matching between
418349cc55cSDimitry Andric // the size of Ins and InVals. This only happens for vararg functions.
419349cc55cSDimitry Andric if (!OutChains.empty()) {
420349cc55cSDimitry Andric OutChains.push_back(Chain);
421349cc55cSDimitry Andric Chain = DAG.getNode(ISD::TokenFactor, DL, MVT::Other, OutChains);
422349cc55cSDimitry Andric }
423349cc55cSDimitry Andric
424349cc55cSDimitry Andric return Chain;
425349cc55cSDimitry Andric }
426349cc55cSDimitry Andric
CanLowerReturn(CallingConv::ID CallConv,MachineFunction & MF,bool IsVarArg,const SmallVectorImpl<ISD::OutputArg> & Outs,LLVMContext & Context) const427349cc55cSDimitry Andric bool CSKYTargetLowering::CanLowerReturn(
428349cc55cSDimitry Andric CallingConv::ID CallConv, MachineFunction &MF, bool IsVarArg,
429349cc55cSDimitry Andric const SmallVectorImpl<ISD::OutputArg> &Outs, LLVMContext &Context) const {
430349cc55cSDimitry Andric SmallVector<CCValAssign, 16> CSKYLocs;
431349cc55cSDimitry Andric CCState CCInfo(CallConv, IsVarArg, MF, CSKYLocs, Context);
432349cc55cSDimitry Andric return CCInfo.CheckReturn(Outs, CCAssignFnForReturn(CallConv, IsVarArg));
433349cc55cSDimitry Andric }
434349cc55cSDimitry Andric
435349cc55cSDimitry Andric SDValue
LowerReturn(SDValue Chain,CallingConv::ID CallConv,bool IsVarArg,const SmallVectorImpl<ISD::OutputArg> & Outs,const SmallVectorImpl<SDValue> & OutVals,const SDLoc & DL,SelectionDAG & DAG) const436349cc55cSDimitry Andric CSKYTargetLowering::LowerReturn(SDValue Chain, CallingConv::ID CallConv,
437349cc55cSDimitry Andric bool IsVarArg,
438349cc55cSDimitry Andric const SmallVectorImpl<ISD::OutputArg> &Outs,
439349cc55cSDimitry Andric const SmallVectorImpl<SDValue> &OutVals,
440349cc55cSDimitry Andric const SDLoc &DL, SelectionDAG &DAG) const {
441349cc55cSDimitry Andric // Stores the assignment of the return value to a location.
442349cc55cSDimitry Andric SmallVector<CCValAssign, 16> CSKYLocs;
443349cc55cSDimitry Andric
444349cc55cSDimitry Andric // Info about the registers and stack slot.
445349cc55cSDimitry Andric CCState CCInfo(CallConv, IsVarArg, DAG.getMachineFunction(), CSKYLocs,
446349cc55cSDimitry Andric *DAG.getContext());
447349cc55cSDimitry Andric CCInfo.AnalyzeReturn(Outs, CCAssignFnForReturn(CallConv, IsVarArg));
448349cc55cSDimitry Andric
449349cc55cSDimitry Andric SDValue Glue;
450349cc55cSDimitry Andric SmallVector<SDValue, 4> RetOps(1, Chain);
451349cc55cSDimitry Andric
452349cc55cSDimitry Andric // Copy the result values into the output registers.
453349cc55cSDimitry Andric for (unsigned i = 0, e = CSKYLocs.size(); i < e; ++i) {
454349cc55cSDimitry Andric SDValue Val = OutVals[i];
455349cc55cSDimitry Andric CCValAssign &VA = CSKYLocs[i];
456349cc55cSDimitry Andric assert(VA.isRegLoc() && "Can only return in registers!");
457349cc55cSDimitry Andric
458349cc55cSDimitry Andric bool IsF64OnCSKY = VA.getLocVT() == MVT::i32 && VA.getValVT() == MVT::f64;
459349cc55cSDimitry Andric
460349cc55cSDimitry Andric if (IsF64OnCSKY) {
461349cc55cSDimitry Andric
462349cc55cSDimitry Andric assert(VA.isRegLoc() && "Expected return via registers");
463349cc55cSDimitry Andric SDValue Split64 = DAG.getNode(CSKYISD::BITCAST_TO_LOHI, DL,
464349cc55cSDimitry Andric DAG.getVTList(MVT::i32, MVT::i32), Val);
465349cc55cSDimitry Andric SDValue Lo = Split64.getValue(0);
466349cc55cSDimitry Andric SDValue Hi = Split64.getValue(1);
467349cc55cSDimitry Andric
468349cc55cSDimitry Andric Register RegLo = VA.getLocReg();
469349cc55cSDimitry Andric assert(RegLo < CSKY::R31 && "Invalid register pair");
470349cc55cSDimitry Andric Register RegHi = RegLo + 1;
471349cc55cSDimitry Andric
472349cc55cSDimitry Andric Chain = DAG.getCopyToReg(Chain, DL, RegLo, Lo, Glue);
473349cc55cSDimitry Andric Glue = Chain.getValue(1);
474349cc55cSDimitry Andric RetOps.push_back(DAG.getRegister(RegLo, MVT::i32));
475349cc55cSDimitry Andric Chain = DAG.getCopyToReg(Chain, DL, RegHi, Hi, Glue);
476349cc55cSDimitry Andric Glue = Chain.getValue(1);
477349cc55cSDimitry Andric RetOps.push_back(DAG.getRegister(RegHi, MVT::i32));
478349cc55cSDimitry Andric } else {
479349cc55cSDimitry Andric // Handle a 'normal' return.
480349cc55cSDimitry Andric Val = convertValVTToLocVT(DAG, Val, VA, DL);
481349cc55cSDimitry Andric Chain = DAG.getCopyToReg(Chain, DL, VA.getLocReg(), Val, Glue);
482349cc55cSDimitry Andric
483349cc55cSDimitry Andric // Guarantee that all emitted copies are stuck together.
484349cc55cSDimitry Andric Glue = Chain.getValue(1);
485349cc55cSDimitry Andric RetOps.push_back(DAG.getRegister(VA.getLocReg(), VA.getLocVT()));
486349cc55cSDimitry Andric }
487349cc55cSDimitry Andric }
488349cc55cSDimitry Andric
489349cc55cSDimitry Andric RetOps[0] = Chain; // Update chain.
490349cc55cSDimitry Andric
491349cc55cSDimitry Andric // Add the glue node if we have it.
492349cc55cSDimitry Andric if (Glue.getNode()) {
493349cc55cSDimitry Andric RetOps.push_back(Glue);
494349cc55cSDimitry Andric }
495349cc55cSDimitry Andric
496349cc55cSDimitry Andric // Interrupt service routines use different return instructions.
497349cc55cSDimitry Andric if (DAG.getMachineFunction().getFunction().hasFnAttribute("interrupt"))
498349cc55cSDimitry Andric return DAG.getNode(CSKYISD::NIR, DL, MVT::Other, RetOps);
499349cc55cSDimitry Andric
500349cc55cSDimitry Andric return DAG.getNode(CSKYISD::RET, DL, MVT::Other, RetOps);
501349cc55cSDimitry Andric }
502349cc55cSDimitry Andric
50304eeddc0SDimitry Andric // Lower a call to a callseq_start + CALL + callseq_end chain, and add input
50404eeddc0SDimitry Andric // and output parameter nodes.
LowerCall(CallLoweringInfo & CLI,SmallVectorImpl<SDValue> & InVals) const50504eeddc0SDimitry Andric SDValue CSKYTargetLowering::LowerCall(CallLoweringInfo &CLI,
50604eeddc0SDimitry Andric SmallVectorImpl<SDValue> &InVals) const {
50704eeddc0SDimitry Andric SelectionDAG &DAG = CLI.DAG;
50804eeddc0SDimitry Andric SDLoc &DL = CLI.DL;
50904eeddc0SDimitry Andric SmallVectorImpl<ISD::OutputArg> &Outs = CLI.Outs;
51004eeddc0SDimitry Andric SmallVectorImpl<SDValue> &OutVals = CLI.OutVals;
51104eeddc0SDimitry Andric SmallVectorImpl<ISD::InputArg> &Ins = CLI.Ins;
51204eeddc0SDimitry Andric SDValue Chain = CLI.Chain;
51304eeddc0SDimitry Andric SDValue Callee = CLI.Callee;
51404eeddc0SDimitry Andric bool &IsTailCall = CLI.IsTailCall;
51504eeddc0SDimitry Andric CallingConv::ID CallConv = CLI.CallConv;
51604eeddc0SDimitry Andric bool IsVarArg = CLI.IsVarArg;
51704eeddc0SDimitry Andric EVT PtrVT = getPointerTy(DAG.getDataLayout());
51804eeddc0SDimitry Andric MVT XLenVT = MVT::i32;
51904eeddc0SDimitry Andric
52004eeddc0SDimitry Andric MachineFunction &MF = DAG.getMachineFunction();
52104eeddc0SDimitry Andric
52204eeddc0SDimitry Andric // Analyze the operands of the call, assigning locations to each operand.
52304eeddc0SDimitry Andric SmallVector<CCValAssign, 16> ArgLocs;
52404eeddc0SDimitry Andric CCState ArgCCInfo(CallConv, IsVarArg, MF, ArgLocs, *DAG.getContext());
52504eeddc0SDimitry Andric
52604eeddc0SDimitry Andric ArgCCInfo.AnalyzeCallOperands(Outs, CCAssignFnForCall(CallConv, IsVarArg));
52704eeddc0SDimitry Andric
52804eeddc0SDimitry Andric // Check if it's really possible to do a tail call.
52904eeddc0SDimitry Andric if (IsTailCall)
53004eeddc0SDimitry Andric IsTailCall = false; // TODO: TailCallOptimization;
53104eeddc0SDimitry Andric
53204eeddc0SDimitry Andric if (IsTailCall)
53304eeddc0SDimitry Andric ++NumTailCalls;
53404eeddc0SDimitry Andric else if (CLI.CB && CLI.CB->isMustTailCall())
53504eeddc0SDimitry Andric report_fatal_error("failed to perform tail call elimination on a call "
53604eeddc0SDimitry Andric "site marked musttail");
53704eeddc0SDimitry Andric
53804eeddc0SDimitry Andric // Get a count of how many bytes are to be pushed on the stack.
53906c3fb27SDimitry Andric unsigned NumBytes = ArgCCInfo.getStackSize();
54004eeddc0SDimitry Andric
54104eeddc0SDimitry Andric // Create local copies for byval args
54204eeddc0SDimitry Andric SmallVector<SDValue, 8> ByValArgs;
54304eeddc0SDimitry Andric for (unsigned i = 0, e = Outs.size(); i != e; ++i) {
54404eeddc0SDimitry Andric ISD::ArgFlagsTy Flags = Outs[i].Flags;
54504eeddc0SDimitry Andric if (!Flags.isByVal())
54604eeddc0SDimitry Andric continue;
54704eeddc0SDimitry Andric
54804eeddc0SDimitry Andric SDValue Arg = OutVals[i];
54904eeddc0SDimitry Andric unsigned Size = Flags.getByValSize();
55004eeddc0SDimitry Andric Align Alignment = Flags.getNonZeroByValAlign();
55104eeddc0SDimitry Andric
55204eeddc0SDimitry Andric int FI =
55304eeddc0SDimitry Andric MF.getFrameInfo().CreateStackObject(Size, Alignment, /*isSS=*/false);
55404eeddc0SDimitry Andric SDValue FIPtr = DAG.getFrameIndex(FI, getPointerTy(DAG.getDataLayout()));
55504eeddc0SDimitry Andric SDValue SizeNode = DAG.getConstant(Size, DL, XLenVT);
55604eeddc0SDimitry Andric
55704eeddc0SDimitry Andric Chain = DAG.getMemcpy(Chain, DL, FIPtr, Arg, SizeNode, Alignment,
55804eeddc0SDimitry Andric /*IsVolatile=*/false,
559*0fca6ea1SDimitry Andric /*AlwaysInline=*/false, /*CI=*/nullptr, IsTailCall,
56004eeddc0SDimitry Andric MachinePointerInfo(), MachinePointerInfo());
56104eeddc0SDimitry Andric ByValArgs.push_back(FIPtr);
56204eeddc0SDimitry Andric }
56304eeddc0SDimitry Andric
56404eeddc0SDimitry Andric if (!IsTailCall)
56504eeddc0SDimitry Andric Chain = DAG.getCALLSEQ_START(Chain, NumBytes, 0, CLI.DL);
56604eeddc0SDimitry Andric
56704eeddc0SDimitry Andric // Copy argument values to their designated locations.
56804eeddc0SDimitry Andric SmallVector<std::pair<Register, SDValue>, 8> RegsToPass;
56904eeddc0SDimitry Andric SmallVector<SDValue, 8> MemOpChains;
57004eeddc0SDimitry Andric SDValue StackPtr;
57104eeddc0SDimitry Andric for (unsigned i = 0, j = 0, e = ArgLocs.size(); i != e; ++i) {
57204eeddc0SDimitry Andric CCValAssign &VA = ArgLocs[i];
57304eeddc0SDimitry Andric SDValue ArgValue = OutVals[i];
57404eeddc0SDimitry Andric ISD::ArgFlagsTy Flags = Outs[i].Flags;
57504eeddc0SDimitry Andric
57604eeddc0SDimitry Andric bool IsF64OnCSKY = VA.getLocVT() == MVT::i32 && VA.getValVT() == MVT::f64;
57704eeddc0SDimitry Andric
57804eeddc0SDimitry Andric if (IsF64OnCSKY && VA.isRegLoc()) {
57904eeddc0SDimitry Andric SDValue Split64 =
58004eeddc0SDimitry Andric DAG.getNode(CSKYISD::BITCAST_TO_LOHI, DL,
58104eeddc0SDimitry Andric DAG.getVTList(MVT::i32, MVT::i32), ArgValue);
58204eeddc0SDimitry Andric SDValue Lo = Split64.getValue(0);
58304eeddc0SDimitry Andric SDValue Hi = Split64.getValue(1);
58404eeddc0SDimitry Andric
58504eeddc0SDimitry Andric Register RegLo = VA.getLocReg();
58604eeddc0SDimitry Andric RegsToPass.push_back(std::make_pair(RegLo, Lo));
58704eeddc0SDimitry Andric
58804eeddc0SDimitry Andric if (RegLo == CSKY::R3) {
58904eeddc0SDimitry Andric // Second half of f64/i64 is passed on the stack.
59004eeddc0SDimitry Andric // Work out the address of the stack slot.
59104eeddc0SDimitry Andric if (!StackPtr.getNode())
59204eeddc0SDimitry Andric StackPtr = DAG.getCopyFromReg(Chain, DL, CSKY::R14, PtrVT);
59304eeddc0SDimitry Andric // Emit the store.
59404eeddc0SDimitry Andric MemOpChains.push_back(
59504eeddc0SDimitry Andric DAG.getStore(Chain, DL, Hi, StackPtr, MachinePointerInfo()));
59604eeddc0SDimitry Andric } else {
59704eeddc0SDimitry Andric // Second half of f64/i64 is passed in another GPR.
59804eeddc0SDimitry Andric assert(RegLo < CSKY::R31 && "Invalid register pair");
59904eeddc0SDimitry Andric Register RegHigh = RegLo + 1;
60004eeddc0SDimitry Andric RegsToPass.push_back(std::make_pair(RegHigh, Hi));
60104eeddc0SDimitry Andric }
60204eeddc0SDimitry Andric continue;
60304eeddc0SDimitry Andric }
60404eeddc0SDimitry Andric
60504eeddc0SDimitry Andric ArgValue = convertValVTToLocVT(DAG, ArgValue, VA, DL);
60604eeddc0SDimitry Andric
60704eeddc0SDimitry Andric // Use local copy if it is a byval arg.
60804eeddc0SDimitry Andric if (Flags.isByVal())
60904eeddc0SDimitry Andric ArgValue = ByValArgs[j++];
61004eeddc0SDimitry Andric
61104eeddc0SDimitry Andric if (VA.isRegLoc()) {
61204eeddc0SDimitry Andric // Queue up the argument copies and emit them at the end.
61304eeddc0SDimitry Andric RegsToPass.push_back(std::make_pair(VA.getLocReg(), ArgValue));
61404eeddc0SDimitry Andric } else {
61504eeddc0SDimitry Andric assert(VA.isMemLoc() && "Argument not register or memory");
61604eeddc0SDimitry Andric assert(!IsTailCall && "Tail call not allowed if stack is used "
61704eeddc0SDimitry Andric "for passing parameters");
61804eeddc0SDimitry Andric
61904eeddc0SDimitry Andric // Work out the address of the stack slot.
62004eeddc0SDimitry Andric if (!StackPtr.getNode())
62104eeddc0SDimitry Andric StackPtr = DAG.getCopyFromReg(Chain, DL, CSKY::R14, PtrVT);
62204eeddc0SDimitry Andric SDValue Address =
62304eeddc0SDimitry Andric DAG.getNode(ISD::ADD, DL, PtrVT, StackPtr,
62404eeddc0SDimitry Andric DAG.getIntPtrConstant(VA.getLocMemOffset(), DL));
62504eeddc0SDimitry Andric
62604eeddc0SDimitry Andric // Emit the store.
62704eeddc0SDimitry Andric MemOpChains.push_back(
62804eeddc0SDimitry Andric DAG.getStore(Chain, DL, ArgValue, Address, MachinePointerInfo()));
62904eeddc0SDimitry Andric }
63004eeddc0SDimitry Andric }
63104eeddc0SDimitry Andric
63204eeddc0SDimitry Andric // Join the stores, which are independent of one another.
63304eeddc0SDimitry Andric if (!MemOpChains.empty())
63404eeddc0SDimitry Andric Chain = DAG.getNode(ISD::TokenFactor, DL, MVT::Other, MemOpChains);
63504eeddc0SDimitry Andric
63604eeddc0SDimitry Andric SDValue Glue;
63704eeddc0SDimitry Andric
63804eeddc0SDimitry Andric // Build a sequence of copy-to-reg nodes, chained and glued together.
63904eeddc0SDimitry Andric for (auto &Reg : RegsToPass) {
64004eeddc0SDimitry Andric Chain = DAG.getCopyToReg(Chain, DL, Reg.first, Reg.second, Glue);
64104eeddc0SDimitry Andric Glue = Chain.getValue(1);
64204eeddc0SDimitry Andric }
64304eeddc0SDimitry Andric
64404eeddc0SDimitry Andric SmallVector<SDValue, 8> Ops;
64504eeddc0SDimitry Andric EVT Ty = getPointerTy(DAG.getDataLayout());
64604eeddc0SDimitry Andric bool IsRegCall = false;
64704eeddc0SDimitry Andric
64804eeddc0SDimitry Andric Ops.push_back(Chain);
64904eeddc0SDimitry Andric
65004eeddc0SDimitry Andric if (GlobalAddressSDNode *S = dyn_cast<GlobalAddressSDNode>(Callee)) {
65104eeddc0SDimitry Andric const GlobalValue *GV = S->getGlobal();
652*0fca6ea1SDimitry Andric bool IsLocal = getTargetMachine().shouldAssumeDSOLocal(GV);
65304eeddc0SDimitry Andric
65404eeddc0SDimitry Andric if (isPositionIndependent() || !Subtarget.has2E3()) {
65504eeddc0SDimitry Andric IsRegCall = true;
65604eeddc0SDimitry Andric Ops.push_back(getAddr<GlobalAddressSDNode, true>(S, DAG, IsLocal));
65704eeddc0SDimitry Andric } else {
65804eeddc0SDimitry Andric Ops.push_back(getTargetNode(cast<GlobalAddressSDNode>(Callee), DL, Ty,
65904eeddc0SDimitry Andric DAG, CSKYII::MO_None));
66004eeddc0SDimitry Andric Ops.push_back(getTargetConstantPoolValue(
66104eeddc0SDimitry Andric cast<GlobalAddressSDNode>(Callee), Ty, DAG, CSKYII::MO_None));
66204eeddc0SDimitry Andric }
66304eeddc0SDimitry Andric } else if (ExternalSymbolSDNode *S = dyn_cast<ExternalSymbolSDNode>(Callee)) {
664*0fca6ea1SDimitry Andric bool IsLocal = getTargetMachine().shouldAssumeDSOLocal(nullptr);
66504eeddc0SDimitry Andric
66604eeddc0SDimitry Andric if (isPositionIndependent() || !Subtarget.has2E3()) {
66704eeddc0SDimitry Andric IsRegCall = true;
66804eeddc0SDimitry Andric Ops.push_back(getAddr<ExternalSymbolSDNode, true>(S, DAG, IsLocal));
66904eeddc0SDimitry Andric } else {
67004eeddc0SDimitry Andric Ops.push_back(getTargetNode(cast<ExternalSymbolSDNode>(Callee), DL, Ty,
67104eeddc0SDimitry Andric DAG, CSKYII::MO_None));
67204eeddc0SDimitry Andric Ops.push_back(getTargetConstantPoolValue(
67304eeddc0SDimitry Andric cast<ExternalSymbolSDNode>(Callee), Ty, DAG, CSKYII::MO_None));
67404eeddc0SDimitry Andric }
67504eeddc0SDimitry Andric } else {
67604eeddc0SDimitry Andric IsRegCall = true;
67704eeddc0SDimitry Andric Ops.push_back(Callee);
67804eeddc0SDimitry Andric }
67904eeddc0SDimitry Andric
68004eeddc0SDimitry Andric // Add argument registers to the end of the list so that they are
68104eeddc0SDimitry Andric // known live into the call.
68204eeddc0SDimitry Andric for (auto &Reg : RegsToPass)
68304eeddc0SDimitry Andric Ops.push_back(DAG.getRegister(Reg.first, Reg.second.getValueType()));
68404eeddc0SDimitry Andric
68504eeddc0SDimitry Andric if (!IsTailCall) {
68604eeddc0SDimitry Andric // Add a register mask operand representing the call-preserved registers.
68704eeddc0SDimitry Andric const TargetRegisterInfo *TRI = Subtarget.getRegisterInfo();
68804eeddc0SDimitry Andric const uint32_t *Mask = TRI->getCallPreservedMask(MF, CallConv);
68904eeddc0SDimitry Andric assert(Mask && "Missing call preserved mask for calling convention");
69004eeddc0SDimitry Andric Ops.push_back(DAG.getRegisterMask(Mask));
69104eeddc0SDimitry Andric }
69204eeddc0SDimitry Andric
69304eeddc0SDimitry Andric // Glue the call to the argument copies, if any.
69404eeddc0SDimitry Andric if (Glue.getNode())
69504eeddc0SDimitry Andric Ops.push_back(Glue);
69604eeddc0SDimitry Andric
69704eeddc0SDimitry Andric // Emit the call.
69804eeddc0SDimitry Andric SDVTList NodeTys = DAG.getVTList(MVT::Other, MVT::Glue);
69904eeddc0SDimitry Andric
70004eeddc0SDimitry Andric if (IsTailCall) {
70104eeddc0SDimitry Andric MF.getFrameInfo().setHasTailCall();
70204eeddc0SDimitry Andric return DAG.getNode(IsRegCall ? CSKYISD::TAILReg : CSKYISD::TAIL, DL,
70304eeddc0SDimitry Andric NodeTys, Ops);
70404eeddc0SDimitry Andric }
70504eeddc0SDimitry Andric
70604eeddc0SDimitry Andric Chain = DAG.getNode(IsRegCall ? CSKYISD::CALLReg : CSKYISD::CALL, DL, NodeTys,
70704eeddc0SDimitry Andric Ops);
70804eeddc0SDimitry Andric DAG.addNoMergeSiteInfo(Chain.getNode(), CLI.NoMerge);
70904eeddc0SDimitry Andric Glue = Chain.getValue(1);
71004eeddc0SDimitry Andric
71104eeddc0SDimitry Andric // Mark the end of the call, which is glued to the call itself.
712bdd1243dSDimitry Andric Chain = DAG.getCALLSEQ_END(Chain, NumBytes, 0, Glue, DL);
71304eeddc0SDimitry Andric Glue = Chain.getValue(1);
71404eeddc0SDimitry Andric
71504eeddc0SDimitry Andric // Assign locations to each value returned by this call.
71604eeddc0SDimitry Andric SmallVector<CCValAssign, 16> CSKYLocs;
71704eeddc0SDimitry Andric CCState RetCCInfo(CallConv, IsVarArg, MF, CSKYLocs, *DAG.getContext());
71804eeddc0SDimitry Andric RetCCInfo.AnalyzeCallResult(Ins, CCAssignFnForReturn(CallConv, IsVarArg));
71904eeddc0SDimitry Andric
72004eeddc0SDimitry Andric // Copy all of the result registers out of their specified physreg.
72104eeddc0SDimitry Andric for (auto &VA : CSKYLocs) {
72204eeddc0SDimitry Andric // Copy the value out
72304eeddc0SDimitry Andric SDValue RetValue =
72404eeddc0SDimitry Andric DAG.getCopyFromReg(Chain, DL, VA.getLocReg(), VA.getLocVT(), Glue);
72504eeddc0SDimitry Andric // Glue the RetValue to the end of the call sequence
72604eeddc0SDimitry Andric Chain = RetValue.getValue(1);
72704eeddc0SDimitry Andric Glue = RetValue.getValue(2);
72804eeddc0SDimitry Andric
72904eeddc0SDimitry Andric bool IsF64OnCSKY = VA.getLocVT() == MVT::i32 && VA.getValVT() == MVT::f64;
73004eeddc0SDimitry Andric
73104eeddc0SDimitry Andric if (IsF64OnCSKY) {
73204eeddc0SDimitry Andric assert(VA.getLocReg() == GPRArgRegs[0] && "Unexpected reg assignment");
73304eeddc0SDimitry Andric SDValue RetValue2 =
73404eeddc0SDimitry Andric DAG.getCopyFromReg(Chain, DL, GPRArgRegs[1], MVT::i32, Glue);
73504eeddc0SDimitry Andric Chain = RetValue2.getValue(1);
73604eeddc0SDimitry Andric Glue = RetValue2.getValue(2);
73704eeddc0SDimitry Andric RetValue = DAG.getNode(CSKYISD::BITCAST_FROM_LOHI, DL, VA.getValVT(),
73804eeddc0SDimitry Andric RetValue, RetValue2);
73904eeddc0SDimitry Andric }
74004eeddc0SDimitry Andric
74104eeddc0SDimitry Andric RetValue = convertLocVTToValVT(DAG, RetValue, VA, DL);
74204eeddc0SDimitry Andric
74304eeddc0SDimitry Andric InVals.push_back(RetValue);
74404eeddc0SDimitry Andric }
74504eeddc0SDimitry Andric
74604eeddc0SDimitry Andric return Chain;
74704eeddc0SDimitry Andric }
74804eeddc0SDimitry Andric
CCAssignFnForReturn(CallingConv::ID CC,bool IsVarArg) const749349cc55cSDimitry Andric CCAssignFn *CSKYTargetLowering::CCAssignFnForReturn(CallingConv::ID CC,
750349cc55cSDimitry Andric bool IsVarArg) const {
751349cc55cSDimitry Andric if (IsVarArg || !Subtarget.useHardFloatABI())
752349cc55cSDimitry Andric return RetCC_CSKY_ABIV2_SOFT;
753349cc55cSDimitry Andric else
754349cc55cSDimitry Andric return RetCC_CSKY_ABIV2_FP;
755349cc55cSDimitry Andric }
756349cc55cSDimitry Andric
CCAssignFnForCall(CallingConv::ID CC,bool IsVarArg) const757349cc55cSDimitry Andric CCAssignFn *CSKYTargetLowering::CCAssignFnForCall(CallingConv::ID CC,
758349cc55cSDimitry Andric bool IsVarArg) const {
759349cc55cSDimitry Andric if (IsVarArg || !Subtarget.useHardFloatABI())
760349cc55cSDimitry Andric return CC_CSKY_ABIV2_SOFT;
761349cc55cSDimitry Andric else
762349cc55cSDimitry Andric return CC_CSKY_ABIV2_FP;
763349cc55cSDimitry Andric }
764349cc55cSDimitry Andric
getModifier(unsigned Flags)76504eeddc0SDimitry Andric static CSKYCP::CSKYCPModifier getModifier(unsigned Flags) {
76604eeddc0SDimitry Andric
76704eeddc0SDimitry Andric if (Flags == CSKYII::MO_ADDR32)
76804eeddc0SDimitry Andric return CSKYCP::ADDR;
76904eeddc0SDimitry Andric else if (Flags == CSKYII::MO_GOT32)
77004eeddc0SDimitry Andric return CSKYCP::GOT;
77104eeddc0SDimitry Andric else if (Flags == CSKYII::MO_GOTOFF)
77204eeddc0SDimitry Andric return CSKYCP::GOTOFF;
77304eeddc0SDimitry Andric else if (Flags == CSKYII::MO_PLT32)
77404eeddc0SDimitry Andric return CSKYCP::PLT;
77504eeddc0SDimitry Andric else if (Flags == CSKYII::MO_None)
77604eeddc0SDimitry Andric return CSKYCP::NO_MOD;
77704eeddc0SDimitry Andric else
77804eeddc0SDimitry Andric assert(0 && "unknown CSKYII Modifier");
77904eeddc0SDimitry Andric return CSKYCP::NO_MOD;
78004eeddc0SDimitry Andric }
78104eeddc0SDimitry Andric
getTargetConstantPoolValue(GlobalAddressSDNode * N,EVT Ty,SelectionDAG & DAG,unsigned Flags) const78204eeddc0SDimitry Andric SDValue CSKYTargetLowering::getTargetConstantPoolValue(GlobalAddressSDNode *N,
78304eeddc0SDimitry Andric EVT Ty,
78404eeddc0SDimitry Andric SelectionDAG &DAG,
78504eeddc0SDimitry Andric unsigned Flags) const {
78604eeddc0SDimitry Andric CSKYConstantPoolValue *CPV = CSKYConstantPoolConstant::Create(
78704eeddc0SDimitry Andric N->getGlobal(), CSKYCP::CPValue, 0, getModifier(Flags), false);
78804eeddc0SDimitry Andric
78904eeddc0SDimitry Andric return DAG.getTargetConstantPool(CPV, Ty);
79004eeddc0SDimitry Andric }
79104eeddc0SDimitry Andric
79281ad6265SDimitry Andric CSKYTargetLowering::ConstraintType
getConstraintType(StringRef Constraint) const79381ad6265SDimitry Andric CSKYTargetLowering::getConstraintType(StringRef Constraint) const {
79481ad6265SDimitry Andric if (Constraint.size() == 1) {
79581ad6265SDimitry Andric switch (Constraint[0]) {
79681ad6265SDimitry Andric default:
79781ad6265SDimitry Andric break;
79881ad6265SDimitry Andric case 'a':
79981ad6265SDimitry Andric case 'b':
80081ad6265SDimitry Andric case 'v':
80181ad6265SDimitry Andric case 'w':
80281ad6265SDimitry Andric case 'y':
80381ad6265SDimitry Andric return C_RegisterClass;
80481ad6265SDimitry Andric case 'c':
80581ad6265SDimitry Andric case 'l':
80681ad6265SDimitry Andric case 'h':
80781ad6265SDimitry Andric case 'z':
80881ad6265SDimitry Andric return C_Register;
80981ad6265SDimitry Andric }
81081ad6265SDimitry Andric }
81181ad6265SDimitry Andric return TargetLowering::getConstraintType(Constraint);
81281ad6265SDimitry Andric }
81381ad6265SDimitry Andric
81481ad6265SDimitry Andric std::pair<unsigned, const TargetRegisterClass *>
getRegForInlineAsmConstraint(const TargetRegisterInfo * TRI,StringRef Constraint,MVT VT) const81581ad6265SDimitry Andric CSKYTargetLowering::getRegForInlineAsmConstraint(const TargetRegisterInfo *TRI,
81681ad6265SDimitry Andric StringRef Constraint,
81781ad6265SDimitry Andric MVT VT) const {
81881ad6265SDimitry Andric if (Constraint.size() == 1) {
81981ad6265SDimitry Andric switch (Constraint[0]) {
82081ad6265SDimitry Andric case 'r':
82181ad6265SDimitry Andric return std::make_pair(0U, &CSKY::GPRRegClass);
82281ad6265SDimitry Andric case 'a':
82381ad6265SDimitry Andric return std::make_pair(0U, &CSKY::mGPRRegClass);
82481ad6265SDimitry Andric case 'b':
82581ad6265SDimitry Andric return std::make_pair(0U, &CSKY::sGPRRegClass);
82681ad6265SDimitry Andric case 'z':
82781ad6265SDimitry Andric return std::make_pair(CSKY::R14, &CSKY::GPRRegClass);
82881ad6265SDimitry Andric case 'c':
82981ad6265SDimitry Andric return std::make_pair(CSKY::C, &CSKY::CARRYRegClass);
83081ad6265SDimitry Andric case 'w':
83181ad6265SDimitry Andric if ((Subtarget.hasFPUv2SingleFloat() ||
83281ad6265SDimitry Andric Subtarget.hasFPUv3SingleFloat()) &&
83381ad6265SDimitry Andric VT == MVT::f32)
83481ad6265SDimitry Andric return std::make_pair(0U, &CSKY::sFPR32RegClass);
83581ad6265SDimitry Andric if ((Subtarget.hasFPUv2DoubleFloat() ||
83681ad6265SDimitry Andric Subtarget.hasFPUv3DoubleFloat()) &&
83781ad6265SDimitry Andric VT == MVT::f64)
83881ad6265SDimitry Andric return std::make_pair(0U, &CSKY::sFPR64RegClass);
83981ad6265SDimitry Andric break;
84081ad6265SDimitry Andric case 'v':
84181ad6265SDimitry Andric if (Subtarget.hasFPUv2SingleFloat() && VT == MVT::f32)
84281ad6265SDimitry Andric return std::make_pair(0U, &CSKY::sFPR32RegClass);
84381ad6265SDimitry Andric if (Subtarget.hasFPUv3SingleFloat() && VT == MVT::f32)
84481ad6265SDimitry Andric return std::make_pair(0U, &CSKY::FPR32RegClass);
84581ad6265SDimitry Andric if (Subtarget.hasFPUv2DoubleFloat() && VT == MVT::f64)
84681ad6265SDimitry Andric return std::make_pair(0U, &CSKY::sFPR64RegClass);
84781ad6265SDimitry Andric if (Subtarget.hasFPUv3DoubleFloat() && VT == MVT::f64)
84881ad6265SDimitry Andric return std::make_pair(0U, &CSKY::FPR64RegClass);
84981ad6265SDimitry Andric break;
85081ad6265SDimitry Andric default:
85181ad6265SDimitry Andric break;
85281ad6265SDimitry Andric }
85381ad6265SDimitry Andric }
85481ad6265SDimitry Andric
85581ad6265SDimitry Andric if (Constraint == "{c}")
85681ad6265SDimitry Andric return std::make_pair(CSKY::C, &CSKY::CARRYRegClass);
85781ad6265SDimitry Andric
85881ad6265SDimitry Andric // Clang will correctly decode the usage of register name aliases into their
85981ad6265SDimitry Andric // official names. However, other frontends like `rustc` do not. This allows
86081ad6265SDimitry Andric // users of these frontends to use the ABI names for registers in LLVM-style
86181ad6265SDimitry Andric // register constraints.
86281ad6265SDimitry Andric unsigned XRegFromAlias = StringSwitch<unsigned>(Constraint.lower())
86381ad6265SDimitry Andric .Case("{a0}", CSKY::R0)
86481ad6265SDimitry Andric .Case("{a1}", CSKY::R1)
86581ad6265SDimitry Andric .Case("{a2}", CSKY::R2)
86681ad6265SDimitry Andric .Case("{a3}", CSKY::R3)
86781ad6265SDimitry Andric .Case("{l0}", CSKY::R4)
86881ad6265SDimitry Andric .Case("{l1}", CSKY::R5)
86981ad6265SDimitry Andric .Case("{l2}", CSKY::R6)
87081ad6265SDimitry Andric .Case("{l3}", CSKY::R7)
87181ad6265SDimitry Andric .Case("{l4}", CSKY::R8)
87281ad6265SDimitry Andric .Case("{l5}", CSKY::R9)
87381ad6265SDimitry Andric .Case("{l6}", CSKY::R10)
87481ad6265SDimitry Andric .Case("{l7}", CSKY::R11)
87581ad6265SDimitry Andric .Case("{t0}", CSKY::R12)
87681ad6265SDimitry Andric .Case("{t1}", CSKY::R13)
87781ad6265SDimitry Andric .Case("{sp}", CSKY::R14)
87881ad6265SDimitry Andric .Case("{lr}", CSKY::R15)
87981ad6265SDimitry Andric .Case("{l8}", CSKY::R16)
88081ad6265SDimitry Andric .Case("{l9}", CSKY::R17)
88181ad6265SDimitry Andric .Case("{t2}", CSKY::R18)
88281ad6265SDimitry Andric .Case("{t3}", CSKY::R19)
88381ad6265SDimitry Andric .Case("{t4}", CSKY::R20)
88481ad6265SDimitry Andric .Case("{t5}", CSKY::R21)
88581ad6265SDimitry Andric .Case("{t6}", CSKY::R22)
88681ad6265SDimitry Andric .Cases("{t7}", "{fp}", CSKY::R23)
88781ad6265SDimitry Andric .Cases("{t8}", "{top}", CSKY::R24)
88881ad6265SDimitry Andric .Cases("{t9}", "{bsp}", CSKY::R25)
88981ad6265SDimitry Andric .Case("{r26}", CSKY::R26)
89081ad6265SDimitry Andric .Case("{r27}", CSKY::R27)
89181ad6265SDimitry Andric .Cases("{gb}", "{rgb}", "{rdb}", CSKY::R28)
89281ad6265SDimitry Andric .Cases("{tb}", "{rtb}", CSKY::R29)
89381ad6265SDimitry Andric .Case("{svbr}", CSKY::R30)
89481ad6265SDimitry Andric .Case("{tls}", CSKY::R31)
89581ad6265SDimitry Andric .Default(CSKY::NoRegister);
89681ad6265SDimitry Andric
89781ad6265SDimitry Andric if (XRegFromAlias != CSKY::NoRegister)
89881ad6265SDimitry Andric return std::make_pair(XRegFromAlias, &CSKY::GPRRegClass);
89981ad6265SDimitry Andric
90081ad6265SDimitry Andric // Since TargetLowering::getRegForInlineAsmConstraint uses the name of the
90181ad6265SDimitry Andric // TableGen record rather than the AsmName to choose registers for InlineAsm
90281ad6265SDimitry Andric // constraints, plus we want to match those names to the widest floating point
90381ad6265SDimitry Andric // register type available, manually select floating point registers here.
90481ad6265SDimitry Andric //
90581ad6265SDimitry Andric // The second case is the ABI name of the register, so that frontends can also
90681ad6265SDimitry Andric // use the ABI names in register constraint lists.
90781ad6265SDimitry Andric if (Subtarget.useHardFloat()) {
90881ad6265SDimitry Andric unsigned FReg = StringSwitch<unsigned>(Constraint.lower())
90981ad6265SDimitry Andric .Cases("{fr0}", "{vr0}", CSKY::F0_32)
91081ad6265SDimitry Andric .Cases("{fr1}", "{vr1}", CSKY::F1_32)
91181ad6265SDimitry Andric .Cases("{fr2}", "{vr2}", CSKY::F2_32)
91281ad6265SDimitry Andric .Cases("{fr3}", "{vr3}", CSKY::F3_32)
91381ad6265SDimitry Andric .Cases("{fr4}", "{vr4}", CSKY::F4_32)
91481ad6265SDimitry Andric .Cases("{fr5}", "{vr5}", CSKY::F5_32)
91581ad6265SDimitry Andric .Cases("{fr6}", "{vr6}", CSKY::F6_32)
91681ad6265SDimitry Andric .Cases("{fr7}", "{vr7}", CSKY::F7_32)
91781ad6265SDimitry Andric .Cases("{fr8}", "{vr8}", CSKY::F8_32)
91881ad6265SDimitry Andric .Cases("{fr9}", "{vr9}", CSKY::F9_32)
91981ad6265SDimitry Andric .Cases("{fr10}", "{vr10}", CSKY::F10_32)
92081ad6265SDimitry Andric .Cases("{fr11}", "{vr11}", CSKY::F11_32)
92181ad6265SDimitry Andric .Cases("{fr12}", "{vr12}", CSKY::F12_32)
92281ad6265SDimitry Andric .Cases("{fr13}", "{vr13}", CSKY::F13_32)
92381ad6265SDimitry Andric .Cases("{fr14}", "{vr14}", CSKY::F14_32)
92481ad6265SDimitry Andric .Cases("{fr15}", "{vr15}", CSKY::F15_32)
92581ad6265SDimitry Andric .Cases("{fr16}", "{vr16}", CSKY::F16_32)
92681ad6265SDimitry Andric .Cases("{fr17}", "{vr17}", CSKY::F17_32)
92781ad6265SDimitry Andric .Cases("{fr18}", "{vr18}", CSKY::F18_32)
92881ad6265SDimitry Andric .Cases("{fr19}", "{vr19}", CSKY::F19_32)
92981ad6265SDimitry Andric .Cases("{fr20}", "{vr20}", CSKY::F20_32)
93081ad6265SDimitry Andric .Cases("{fr21}", "{vr21}", CSKY::F21_32)
93181ad6265SDimitry Andric .Cases("{fr22}", "{vr22}", CSKY::F22_32)
93281ad6265SDimitry Andric .Cases("{fr23}", "{vr23}", CSKY::F23_32)
93381ad6265SDimitry Andric .Cases("{fr24}", "{vr24}", CSKY::F24_32)
93481ad6265SDimitry Andric .Cases("{fr25}", "{vr25}", CSKY::F25_32)
93581ad6265SDimitry Andric .Cases("{fr26}", "{vr26}", CSKY::F26_32)
93681ad6265SDimitry Andric .Cases("{fr27}", "{vr27}", CSKY::F27_32)
93781ad6265SDimitry Andric .Cases("{fr28}", "{vr28}", CSKY::F28_32)
93881ad6265SDimitry Andric .Cases("{fr29}", "{vr29}", CSKY::F29_32)
93981ad6265SDimitry Andric .Cases("{fr30}", "{vr30}", CSKY::F30_32)
94081ad6265SDimitry Andric .Cases("{fr31}", "{vr31}", CSKY::F31_32)
94181ad6265SDimitry Andric .Default(CSKY::NoRegister);
94281ad6265SDimitry Andric if (FReg != CSKY::NoRegister) {
94381ad6265SDimitry Andric assert(CSKY::F0_32 <= FReg && FReg <= CSKY::F31_32 && "Unknown fp-reg");
94481ad6265SDimitry Andric unsigned RegNo = FReg - CSKY::F0_32;
94581ad6265SDimitry Andric unsigned DReg = CSKY::F0_64 + RegNo;
94681ad6265SDimitry Andric
94781ad6265SDimitry Andric if (Subtarget.hasFPUv2DoubleFloat())
94881ad6265SDimitry Andric return std::make_pair(DReg, &CSKY::sFPR64RegClass);
94981ad6265SDimitry Andric else if (Subtarget.hasFPUv3DoubleFloat())
95081ad6265SDimitry Andric return std::make_pair(DReg, &CSKY::FPR64RegClass);
95181ad6265SDimitry Andric else if (Subtarget.hasFPUv2SingleFloat())
95281ad6265SDimitry Andric return std::make_pair(FReg, &CSKY::sFPR32RegClass);
95381ad6265SDimitry Andric else if (Subtarget.hasFPUv3SingleFloat())
95481ad6265SDimitry Andric return std::make_pair(FReg, &CSKY::FPR32RegClass);
95581ad6265SDimitry Andric }
95681ad6265SDimitry Andric }
95781ad6265SDimitry Andric
95881ad6265SDimitry Andric return TargetLowering::getRegForInlineAsmConstraint(TRI, Constraint, VT);
95981ad6265SDimitry Andric }
96081ad6265SDimitry Andric
96104eeddc0SDimitry Andric static MachineBasicBlock *
emitSelectPseudo(MachineInstr & MI,MachineBasicBlock * BB,unsigned Opcode)96204eeddc0SDimitry Andric emitSelectPseudo(MachineInstr &MI, MachineBasicBlock *BB, unsigned Opcode) {
96304eeddc0SDimitry Andric
96404eeddc0SDimitry Andric const TargetInstrInfo &TII = *BB->getParent()->getSubtarget().getInstrInfo();
96504eeddc0SDimitry Andric DebugLoc DL = MI.getDebugLoc();
96604eeddc0SDimitry Andric
96704eeddc0SDimitry Andric // To "insert" a SELECT instruction, we actually have to insert the
96804eeddc0SDimitry Andric // diamond control-flow pattern. The incoming instruction knows the
96904eeddc0SDimitry Andric // destination vreg to set, the condition code register to branch on, the
97004eeddc0SDimitry Andric // true/false values to select between, and a branch opcode to use.
97104eeddc0SDimitry Andric const BasicBlock *LLVM_BB = BB->getBasicBlock();
97204eeddc0SDimitry Andric MachineFunction::iterator It = ++BB->getIterator();
97304eeddc0SDimitry Andric
97404eeddc0SDimitry Andric // thisMBB:
97504eeddc0SDimitry Andric // ...
97604eeddc0SDimitry Andric // TrueVal = ...
97704eeddc0SDimitry Andric // bt32 c, sinkMBB
97804eeddc0SDimitry Andric // fallthrough --> copyMBB
97904eeddc0SDimitry Andric MachineBasicBlock *thisMBB = BB;
98004eeddc0SDimitry Andric MachineFunction *F = BB->getParent();
98104eeddc0SDimitry Andric MachineBasicBlock *copyMBB = F->CreateMachineBasicBlock(LLVM_BB);
98204eeddc0SDimitry Andric MachineBasicBlock *sinkMBB = F->CreateMachineBasicBlock(LLVM_BB);
98304eeddc0SDimitry Andric F->insert(It, copyMBB);
98404eeddc0SDimitry Andric F->insert(It, sinkMBB);
98504eeddc0SDimitry Andric
98604eeddc0SDimitry Andric // Transfer the remainder of BB and its successor edges to sinkMBB.
98704eeddc0SDimitry Andric sinkMBB->splice(sinkMBB->begin(), BB,
98804eeddc0SDimitry Andric std::next(MachineBasicBlock::iterator(MI)), BB->end());
98904eeddc0SDimitry Andric sinkMBB->transferSuccessorsAndUpdatePHIs(BB);
99004eeddc0SDimitry Andric
99104eeddc0SDimitry Andric // Next, add the true and fallthrough blocks as its successors.
99204eeddc0SDimitry Andric BB->addSuccessor(copyMBB);
99304eeddc0SDimitry Andric BB->addSuccessor(sinkMBB);
99404eeddc0SDimitry Andric
99504eeddc0SDimitry Andric // bt32 condition, sinkMBB
99604eeddc0SDimitry Andric BuildMI(BB, DL, TII.get(Opcode))
99704eeddc0SDimitry Andric .addReg(MI.getOperand(1).getReg())
99804eeddc0SDimitry Andric .addMBB(sinkMBB);
99904eeddc0SDimitry Andric
100004eeddc0SDimitry Andric // copyMBB:
100104eeddc0SDimitry Andric // %FalseValue = ...
100204eeddc0SDimitry Andric // # fallthrough to sinkMBB
100304eeddc0SDimitry Andric BB = copyMBB;
100404eeddc0SDimitry Andric
100504eeddc0SDimitry Andric // Update machine-CFG edges
100604eeddc0SDimitry Andric BB->addSuccessor(sinkMBB);
100704eeddc0SDimitry Andric
100804eeddc0SDimitry Andric // sinkMBB:
100904eeddc0SDimitry Andric // %Result = phi [ %TrueValue, thisMBB ], [ %FalseValue, copyMBB ]
101004eeddc0SDimitry Andric // ...
101104eeddc0SDimitry Andric BB = sinkMBB;
101204eeddc0SDimitry Andric
101304eeddc0SDimitry Andric BuildMI(*BB, BB->begin(), DL, TII.get(CSKY::PHI), MI.getOperand(0).getReg())
101404eeddc0SDimitry Andric .addReg(MI.getOperand(2).getReg())
101504eeddc0SDimitry Andric .addMBB(thisMBB)
101604eeddc0SDimitry Andric .addReg(MI.getOperand(3).getReg())
101704eeddc0SDimitry Andric .addMBB(copyMBB);
101804eeddc0SDimitry Andric
101904eeddc0SDimitry Andric MI.eraseFromParent(); // The pseudo instruction is gone now.
102004eeddc0SDimitry Andric
102104eeddc0SDimitry Andric return BB;
102204eeddc0SDimitry Andric }
102304eeddc0SDimitry Andric
102404eeddc0SDimitry Andric MachineBasicBlock *
EmitInstrWithCustomInserter(MachineInstr & MI,MachineBasicBlock * BB) const102504eeddc0SDimitry Andric CSKYTargetLowering::EmitInstrWithCustomInserter(MachineInstr &MI,
102604eeddc0SDimitry Andric MachineBasicBlock *BB) const {
102704eeddc0SDimitry Andric switch (MI.getOpcode()) {
102804eeddc0SDimitry Andric default:
102904eeddc0SDimitry Andric llvm_unreachable("Unexpected instr type to insert");
103081ad6265SDimitry Andric case CSKY::FSELS:
103181ad6265SDimitry Andric case CSKY::FSELD:
103281ad6265SDimitry Andric if (Subtarget.hasE2())
103381ad6265SDimitry Andric return emitSelectPseudo(MI, BB, CSKY::BT32);
103481ad6265SDimitry Andric else
103581ad6265SDimitry Andric return emitSelectPseudo(MI, BB, CSKY::BT16);
103604eeddc0SDimitry Andric case CSKY::ISEL32:
103704eeddc0SDimitry Andric return emitSelectPseudo(MI, BB, CSKY::BT32);
103804eeddc0SDimitry Andric case CSKY::ISEL16:
103904eeddc0SDimitry Andric return emitSelectPseudo(MI, BB, CSKY::BT16);
104004eeddc0SDimitry Andric }
104104eeddc0SDimitry Andric }
104204eeddc0SDimitry Andric
getTargetConstantPoolValue(ExternalSymbolSDNode * N,EVT Ty,SelectionDAG & DAG,unsigned Flags) const104304eeddc0SDimitry Andric SDValue CSKYTargetLowering::getTargetConstantPoolValue(ExternalSymbolSDNode *N,
104404eeddc0SDimitry Andric EVT Ty,
104504eeddc0SDimitry Andric SelectionDAG &DAG,
104604eeddc0SDimitry Andric unsigned Flags) const {
104704eeddc0SDimitry Andric CSKYConstantPoolValue *CPV =
104804eeddc0SDimitry Andric CSKYConstantPoolSymbol::Create(Type::getInt32Ty(*DAG.getContext()),
104904eeddc0SDimitry Andric N->getSymbol(), 0, getModifier(Flags));
105004eeddc0SDimitry Andric
105104eeddc0SDimitry Andric return DAG.getTargetConstantPool(CPV, Ty);
105204eeddc0SDimitry Andric }
105304eeddc0SDimitry Andric
getTargetConstantPoolValue(JumpTableSDNode * N,EVT Ty,SelectionDAG & DAG,unsigned Flags) const105404eeddc0SDimitry Andric SDValue CSKYTargetLowering::getTargetConstantPoolValue(JumpTableSDNode *N,
105504eeddc0SDimitry Andric EVT Ty,
105604eeddc0SDimitry Andric SelectionDAG &DAG,
105704eeddc0SDimitry Andric unsigned Flags) const {
105804eeddc0SDimitry Andric CSKYConstantPoolValue *CPV =
105904eeddc0SDimitry Andric CSKYConstantPoolJT::Create(Type::getInt32Ty(*DAG.getContext()),
106004eeddc0SDimitry Andric N->getIndex(), 0, getModifier(Flags));
106104eeddc0SDimitry Andric return DAG.getTargetConstantPool(CPV, Ty);
106204eeddc0SDimitry Andric }
106304eeddc0SDimitry Andric
getTargetConstantPoolValue(BlockAddressSDNode * N,EVT Ty,SelectionDAG & DAG,unsigned Flags) const106404eeddc0SDimitry Andric SDValue CSKYTargetLowering::getTargetConstantPoolValue(BlockAddressSDNode *N,
106504eeddc0SDimitry Andric EVT Ty,
106604eeddc0SDimitry Andric SelectionDAG &DAG,
106704eeddc0SDimitry Andric unsigned Flags) const {
1068bdd1243dSDimitry Andric assert(N->getOffset() == 0);
106904eeddc0SDimitry Andric CSKYConstantPoolValue *CPV = CSKYConstantPoolConstant::Create(
107004eeddc0SDimitry Andric N->getBlockAddress(), CSKYCP::CPBlockAddress, 0, getModifier(Flags),
107104eeddc0SDimitry Andric false);
107204eeddc0SDimitry Andric return DAG.getTargetConstantPool(CPV, Ty);
107304eeddc0SDimitry Andric }
107404eeddc0SDimitry Andric
getTargetConstantPoolValue(ConstantPoolSDNode * N,EVT Ty,SelectionDAG & DAG,unsigned Flags) const1075bdd1243dSDimitry Andric SDValue CSKYTargetLowering::getTargetConstantPoolValue(ConstantPoolSDNode *N,
1076bdd1243dSDimitry Andric EVT Ty,
1077bdd1243dSDimitry Andric SelectionDAG &DAG,
1078bdd1243dSDimitry Andric unsigned Flags) const {
1079bdd1243dSDimitry Andric assert(N->getOffset() == 0);
1080bdd1243dSDimitry Andric CSKYConstantPoolValue *CPV = CSKYConstantPoolConstant::Create(
1081bdd1243dSDimitry Andric N->getConstVal(), Type::getInt32Ty(*DAG.getContext()),
1082bdd1243dSDimitry Andric CSKYCP::CPConstPool, 0, getModifier(Flags), false);
1083bdd1243dSDimitry Andric return DAG.getTargetConstantPool(CPV, Ty);
1084bdd1243dSDimitry Andric }
1085bdd1243dSDimitry Andric
getTargetNode(GlobalAddressSDNode * N,SDLoc DL,EVT Ty,SelectionDAG & DAG,unsigned Flags) const108604eeddc0SDimitry Andric SDValue CSKYTargetLowering::getTargetNode(GlobalAddressSDNode *N, SDLoc DL,
108704eeddc0SDimitry Andric EVT Ty, SelectionDAG &DAG,
108804eeddc0SDimitry Andric unsigned Flags) const {
108904eeddc0SDimitry Andric return DAG.getTargetGlobalAddress(N->getGlobal(), DL, Ty, 0, Flags);
109004eeddc0SDimitry Andric }
109104eeddc0SDimitry Andric
getTargetNode(ExternalSymbolSDNode * N,SDLoc DL,EVT Ty,SelectionDAG & DAG,unsigned Flags) const109204eeddc0SDimitry Andric SDValue CSKYTargetLowering::getTargetNode(ExternalSymbolSDNode *N, SDLoc DL,
109304eeddc0SDimitry Andric EVT Ty, SelectionDAG &DAG,
109404eeddc0SDimitry Andric unsigned Flags) const {
109504eeddc0SDimitry Andric return DAG.getTargetExternalSymbol(N->getSymbol(), Ty, Flags);
109604eeddc0SDimitry Andric }
109704eeddc0SDimitry Andric
getTargetNode(JumpTableSDNode * N,SDLoc DL,EVT Ty,SelectionDAG & DAG,unsigned Flags) const109804eeddc0SDimitry Andric SDValue CSKYTargetLowering::getTargetNode(JumpTableSDNode *N, SDLoc DL, EVT Ty,
109904eeddc0SDimitry Andric SelectionDAG &DAG,
110004eeddc0SDimitry Andric unsigned Flags) const {
110104eeddc0SDimitry Andric return DAG.getTargetJumpTable(N->getIndex(), Ty, Flags);
110204eeddc0SDimitry Andric }
110304eeddc0SDimitry Andric
getTargetNode(BlockAddressSDNode * N,SDLoc DL,EVT Ty,SelectionDAG & DAG,unsigned Flags) const110404eeddc0SDimitry Andric SDValue CSKYTargetLowering::getTargetNode(BlockAddressSDNode *N, SDLoc DL,
110504eeddc0SDimitry Andric EVT Ty, SelectionDAG &DAG,
110604eeddc0SDimitry Andric unsigned Flags) const {
110704eeddc0SDimitry Andric return DAG.getTargetBlockAddress(N->getBlockAddress(), Ty, N->getOffset(),
110804eeddc0SDimitry Andric Flags);
110904eeddc0SDimitry Andric }
111004eeddc0SDimitry Andric
getTargetNode(ConstantPoolSDNode * N,SDLoc DL,EVT Ty,SelectionDAG & DAG,unsigned Flags) const1111bdd1243dSDimitry Andric SDValue CSKYTargetLowering::getTargetNode(ConstantPoolSDNode *N, SDLoc DL,
1112bdd1243dSDimitry Andric EVT Ty, SelectionDAG &DAG,
1113bdd1243dSDimitry Andric unsigned Flags) const {
1114bdd1243dSDimitry Andric
1115bdd1243dSDimitry Andric return DAG.getTargetConstantPool(N->getConstVal(), Ty, N->getAlign(),
1116bdd1243dSDimitry Andric N->getOffset(), Flags);
1117bdd1243dSDimitry Andric }
1118bdd1243dSDimitry Andric
getTargetNodeName(unsigned Opcode) const1119349cc55cSDimitry Andric const char *CSKYTargetLowering::getTargetNodeName(unsigned Opcode) const {
1120349cc55cSDimitry Andric switch (Opcode) {
1121349cc55cSDimitry Andric default:
1122349cc55cSDimitry Andric llvm_unreachable("unknown CSKYISD node");
1123349cc55cSDimitry Andric case CSKYISD::NIE:
1124349cc55cSDimitry Andric return "CSKYISD::NIE";
1125349cc55cSDimitry Andric case CSKYISD::NIR:
1126349cc55cSDimitry Andric return "CSKYISD::NIR";
1127349cc55cSDimitry Andric case CSKYISD::RET:
1128349cc55cSDimitry Andric return "CSKYISD::RET";
112904eeddc0SDimitry Andric case CSKYISD::CALL:
113004eeddc0SDimitry Andric return "CSKYISD::CALL";
113104eeddc0SDimitry Andric case CSKYISD::CALLReg:
113204eeddc0SDimitry Andric return "CSKYISD::CALLReg";
113304eeddc0SDimitry Andric case CSKYISD::TAIL:
113404eeddc0SDimitry Andric return "CSKYISD::TAIL";
113504eeddc0SDimitry Andric case CSKYISD::TAILReg:
113604eeddc0SDimitry Andric return "CSKYISD::TAILReg";
113704eeddc0SDimitry Andric case CSKYISD::LOAD_ADDR:
113804eeddc0SDimitry Andric return "CSKYISD::LOAD_ADDR";
1139349cc55cSDimitry Andric case CSKYISD::BITCAST_TO_LOHI:
1140349cc55cSDimitry Andric return "CSKYISD::BITCAST_TO_LOHI";
114104eeddc0SDimitry Andric case CSKYISD::BITCAST_FROM_LOHI:
114204eeddc0SDimitry Andric return "CSKYISD::BITCAST_FROM_LOHI";
1143349cc55cSDimitry Andric }
1144349cc55cSDimitry Andric }
114504eeddc0SDimitry Andric
LowerGlobalAddress(SDValue Op,SelectionDAG & DAG) const114604eeddc0SDimitry Andric SDValue CSKYTargetLowering::LowerGlobalAddress(SDValue Op,
114704eeddc0SDimitry Andric SelectionDAG &DAG) const {
114804eeddc0SDimitry Andric SDLoc DL(Op);
114904eeddc0SDimitry Andric EVT Ty = Op.getValueType();
115004eeddc0SDimitry Andric GlobalAddressSDNode *N = cast<GlobalAddressSDNode>(Op);
115104eeddc0SDimitry Andric int64_t Offset = N->getOffset();
115204eeddc0SDimitry Andric
115304eeddc0SDimitry Andric const GlobalValue *GV = N->getGlobal();
1154*0fca6ea1SDimitry Andric bool IsLocal = getTargetMachine().shouldAssumeDSOLocal(GV);
115504eeddc0SDimitry Andric SDValue Addr = getAddr<GlobalAddressSDNode, false>(N, DAG, IsLocal);
115604eeddc0SDimitry Andric
115704eeddc0SDimitry Andric // In order to maximise the opportunity for common subexpression elimination,
115804eeddc0SDimitry Andric // emit a separate ADD node for the global address offset instead of folding
115904eeddc0SDimitry Andric // it in the global address node. Later peephole optimisations may choose to
116004eeddc0SDimitry Andric // fold it back in when profitable.
116104eeddc0SDimitry Andric if (Offset != 0)
116204eeddc0SDimitry Andric return DAG.getNode(ISD::ADD, DL, Ty, Addr,
116304eeddc0SDimitry Andric DAG.getConstant(Offset, DL, MVT::i32));
116404eeddc0SDimitry Andric return Addr;
116504eeddc0SDimitry Andric }
116604eeddc0SDimitry Andric
LowerExternalSymbol(SDValue Op,SelectionDAG & DAG) const116704eeddc0SDimitry Andric SDValue CSKYTargetLowering::LowerExternalSymbol(SDValue Op,
116804eeddc0SDimitry Andric SelectionDAG &DAG) const {
116904eeddc0SDimitry Andric ExternalSymbolSDNode *N = cast<ExternalSymbolSDNode>(Op);
117004eeddc0SDimitry Andric
117104eeddc0SDimitry Andric return getAddr(N, DAG, false);
117204eeddc0SDimitry Andric }
117304eeddc0SDimitry Andric
LowerJumpTable(SDValue Op,SelectionDAG & DAG) const117404eeddc0SDimitry Andric SDValue CSKYTargetLowering::LowerJumpTable(SDValue Op,
117504eeddc0SDimitry Andric SelectionDAG &DAG) const {
117604eeddc0SDimitry Andric JumpTableSDNode *N = cast<JumpTableSDNode>(Op);
117704eeddc0SDimitry Andric
117804eeddc0SDimitry Andric return getAddr<JumpTableSDNode, false>(N, DAG);
117904eeddc0SDimitry Andric }
118004eeddc0SDimitry Andric
LowerBlockAddress(SDValue Op,SelectionDAG & DAG) const118104eeddc0SDimitry Andric SDValue CSKYTargetLowering::LowerBlockAddress(SDValue Op,
118204eeddc0SDimitry Andric SelectionDAG &DAG) const {
118304eeddc0SDimitry Andric BlockAddressSDNode *N = cast<BlockAddressSDNode>(Op);
118404eeddc0SDimitry Andric
118504eeddc0SDimitry Andric return getAddr(N, DAG);
118604eeddc0SDimitry Andric }
118704eeddc0SDimitry Andric
LowerConstantPool(SDValue Op,SelectionDAG & DAG) const1188bdd1243dSDimitry Andric SDValue CSKYTargetLowering::LowerConstantPool(SDValue Op,
1189bdd1243dSDimitry Andric SelectionDAG &DAG) const {
1190bdd1243dSDimitry Andric assert(!Subtarget.hasE2());
1191bdd1243dSDimitry Andric ConstantPoolSDNode *N = cast<ConstantPoolSDNode>(Op);
1192bdd1243dSDimitry Andric
1193bdd1243dSDimitry Andric return getAddr(N, DAG);
1194bdd1243dSDimitry Andric }
1195bdd1243dSDimitry Andric
LowerVASTART(SDValue Op,SelectionDAG & DAG) const119604eeddc0SDimitry Andric SDValue CSKYTargetLowering::LowerVASTART(SDValue Op, SelectionDAG &DAG) const {
119704eeddc0SDimitry Andric MachineFunction &MF = DAG.getMachineFunction();
119804eeddc0SDimitry Andric CSKYMachineFunctionInfo *FuncInfo = MF.getInfo<CSKYMachineFunctionInfo>();
119904eeddc0SDimitry Andric
120004eeddc0SDimitry Andric SDLoc DL(Op);
120104eeddc0SDimitry Andric SDValue FI = DAG.getFrameIndex(FuncInfo->getVarArgsFrameIndex(),
120204eeddc0SDimitry Andric getPointerTy(MF.getDataLayout()));
120304eeddc0SDimitry Andric
120404eeddc0SDimitry Andric // vastart just stores the address of the VarArgsFrameIndex slot into the
120504eeddc0SDimitry Andric // memory location argument.
120604eeddc0SDimitry Andric const Value *SV = cast<SrcValueSDNode>(Op.getOperand(2))->getValue();
120704eeddc0SDimitry Andric return DAG.getStore(Op.getOperand(0), DL, FI, Op.getOperand(1),
120804eeddc0SDimitry Andric MachinePointerInfo(SV));
120904eeddc0SDimitry Andric }
121004eeddc0SDimitry Andric
LowerFRAMEADDR(SDValue Op,SelectionDAG & DAG) const121104eeddc0SDimitry Andric SDValue CSKYTargetLowering::LowerFRAMEADDR(SDValue Op,
121204eeddc0SDimitry Andric SelectionDAG &DAG) const {
121304eeddc0SDimitry Andric const CSKYRegisterInfo &RI = *Subtarget.getRegisterInfo();
121404eeddc0SDimitry Andric MachineFunction &MF = DAG.getMachineFunction();
121504eeddc0SDimitry Andric MachineFrameInfo &MFI = MF.getFrameInfo();
121604eeddc0SDimitry Andric MFI.setFrameAddressIsTaken(true);
121704eeddc0SDimitry Andric
121804eeddc0SDimitry Andric EVT VT = Op.getValueType();
121904eeddc0SDimitry Andric SDLoc dl(Op);
1220647cbc5dSDimitry Andric unsigned Depth = Op.getConstantOperandVal(0);
122104eeddc0SDimitry Andric Register FrameReg = RI.getFrameRegister(MF);
122204eeddc0SDimitry Andric SDValue FrameAddr = DAG.getCopyFromReg(DAG.getEntryNode(), dl, FrameReg, VT);
122304eeddc0SDimitry Andric while (Depth--)
122404eeddc0SDimitry Andric FrameAddr = DAG.getLoad(VT, dl, DAG.getEntryNode(), FrameAddr,
122504eeddc0SDimitry Andric MachinePointerInfo());
122604eeddc0SDimitry Andric return FrameAddr;
122704eeddc0SDimitry Andric }
122804eeddc0SDimitry Andric
LowerRETURNADDR(SDValue Op,SelectionDAG & DAG) const122904eeddc0SDimitry Andric SDValue CSKYTargetLowering::LowerRETURNADDR(SDValue Op,
123004eeddc0SDimitry Andric SelectionDAG &DAG) const {
123104eeddc0SDimitry Andric const CSKYRegisterInfo &RI = *Subtarget.getRegisterInfo();
123204eeddc0SDimitry Andric MachineFunction &MF = DAG.getMachineFunction();
123304eeddc0SDimitry Andric MachineFrameInfo &MFI = MF.getFrameInfo();
123404eeddc0SDimitry Andric MFI.setReturnAddressIsTaken(true);
123504eeddc0SDimitry Andric
123604eeddc0SDimitry Andric if (verifyReturnAddressArgumentIsConstant(Op, DAG))
123704eeddc0SDimitry Andric return SDValue();
123804eeddc0SDimitry Andric
123904eeddc0SDimitry Andric EVT VT = Op.getValueType();
124004eeddc0SDimitry Andric SDLoc dl(Op);
1241647cbc5dSDimitry Andric unsigned Depth = Op.getConstantOperandVal(0);
124204eeddc0SDimitry Andric if (Depth) {
124304eeddc0SDimitry Andric SDValue FrameAddr = LowerFRAMEADDR(Op, DAG);
124404eeddc0SDimitry Andric SDValue Offset = DAG.getConstant(4, dl, MVT::i32);
124504eeddc0SDimitry Andric return DAG.getLoad(VT, dl, DAG.getEntryNode(),
124604eeddc0SDimitry Andric DAG.getNode(ISD::ADD, dl, VT, FrameAddr, Offset),
124704eeddc0SDimitry Andric MachinePointerInfo());
124804eeddc0SDimitry Andric }
124904eeddc0SDimitry Andric // Return the value of the return address register, marking it an implicit
125004eeddc0SDimitry Andric // live-in.
125104eeddc0SDimitry Andric unsigned Reg = MF.addLiveIn(RI.getRARegister(), getRegClassFor(MVT::i32));
125204eeddc0SDimitry Andric return DAG.getCopyFromReg(DAG.getEntryNode(), dl, Reg, VT);
125304eeddc0SDimitry Andric }
125404eeddc0SDimitry Andric
getExceptionPointerRegister(const Constant * PersonalityFn) const125504eeddc0SDimitry Andric Register CSKYTargetLowering::getExceptionPointerRegister(
125604eeddc0SDimitry Andric const Constant *PersonalityFn) const {
125704eeddc0SDimitry Andric return CSKY::R0;
125804eeddc0SDimitry Andric }
125904eeddc0SDimitry Andric
getExceptionSelectorRegister(const Constant * PersonalityFn) const126004eeddc0SDimitry Andric Register CSKYTargetLowering::getExceptionSelectorRegister(
126104eeddc0SDimitry Andric const Constant *PersonalityFn) const {
126204eeddc0SDimitry Andric return CSKY::R1;
126304eeddc0SDimitry Andric }
126404eeddc0SDimitry Andric
LowerGlobalTLSAddress(SDValue Op,SelectionDAG & DAG) const126504eeddc0SDimitry Andric SDValue CSKYTargetLowering::LowerGlobalTLSAddress(SDValue Op,
126604eeddc0SDimitry Andric SelectionDAG &DAG) const {
126704eeddc0SDimitry Andric SDLoc DL(Op);
126804eeddc0SDimitry Andric EVT Ty = Op.getValueType();
126904eeddc0SDimitry Andric GlobalAddressSDNode *N = cast<GlobalAddressSDNode>(Op);
127004eeddc0SDimitry Andric int64_t Offset = N->getOffset();
127104eeddc0SDimitry Andric MVT XLenVT = MVT::i32;
127204eeddc0SDimitry Andric
127304eeddc0SDimitry Andric TLSModel::Model Model = getTargetMachine().getTLSModel(N->getGlobal());
127404eeddc0SDimitry Andric SDValue Addr;
127504eeddc0SDimitry Andric switch (Model) {
127604eeddc0SDimitry Andric case TLSModel::LocalExec:
127704eeddc0SDimitry Andric Addr = getStaticTLSAddr(N, DAG, /*UseGOT=*/false);
127804eeddc0SDimitry Andric break;
127904eeddc0SDimitry Andric case TLSModel::InitialExec:
128004eeddc0SDimitry Andric Addr = getStaticTLSAddr(N, DAG, /*UseGOT=*/true);
128104eeddc0SDimitry Andric break;
128204eeddc0SDimitry Andric case TLSModel::LocalDynamic:
128304eeddc0SDimitry Andric case TLSModel::GeneralDynamic:
128404eeddc0SDimitry Andric Addr = getDynamicTLSAddr(N, DAG);
128504eeddc0SDimitry Andric break;
128604eeddc0SDimitry Andric }
128704eeddc0SDimitry Andric
128804eeddc0SDimitry Andric // In order to maximise the opportunity for common subexpression elimination,
128904eeddc0SDimitry Andric // emit a separate ADD node for the global address offset instead of folding
129004eeddc0SDimitry Andric // it in the global address node. Later peephole optimisations may choose to
129104eeddc0SDimitry Andric // fold it back in when profitable.
129204eeddc0SDimitry Andric if (Offset != 0)
129304eeddc0SDimitry Andric return DAG.getNode(ISD::ADD, DL, Ty, Addr,
129404eeddc0SDimitry Andric DAG.getConstant(Offset, DL, XLenVT));
129504eeddc0SDimitry Andric return Addr;
129604eeddc0SDimitry Andric }
129704eeddc0SDimitry Andric
getStaticTLSAddr(GlobalAddressSDNode * N,SelectionDAG & DAG,bool UseGOT) const129804eeddc0SDimitry Andric SDValue CSKYTargetLowering::getStaticTLSAddr(GlobalAddressSDNode *N,
129904eeddc0SDimitry Andric SelectionDAG &DAG,
130004eeddc0SDimitry Andric bool UseGOT) const {
130104eeddc0SDimitry Andric MachineFunction &MF = DAG.getMachineFunction();
130204eeddc0SDimitry Andric CSKYMachineFunctionInfo *CFI = MF.getInfo<CSKYMachineFunctionInfo>();
130304eeddc0SDimitry Andric
130404eeddc0SDimitry Andric unsigned CSKYPCLabelIndex = CFI->createPICLabelUId();
130504eeddc0SDimitry Andric
130604eeddc0SDimitry Andric SDLoc DL(N);
130704eeddc0SDimitry Andric EVT Ty = getPointerTy(DAG.getDataLayout());
130804eeddc0SDimitry Andric
130904eeddc0SDimitry Andric CSKYCP::CSKYCPModifier Flag = UseGOT ? CSKYCP::TLSIE : CSKYCP::TLSLE;
131004eeddc0SDimitry Andric bool AddCurrentAddr = UseGOT ? true : false;
131104eeddc0SDimitry Andric unsigned char PCAjust = UseGOT ? 4 : 0;
131204eeddc0SDimitry Andric
131304eeddc0SDimitry Andric CSKYConstantPoolValue *CPV =
131404eeddc0SDimitry Andric CSKYConstantPoolConstant::Create(N->getGlobal(), CSKYCP::CPValue, PCAjust,
131504eeddc0SDimitry Andric Flag, AddCurrentAddr, CSKYPCLabelIndex);
131604eeddc0SDimitry Andric SDValue CAddr = DAG.getTargetConstantPool(CPV, Ty);
131704eeddc0SDimitry Andric
131804eeddc0SDimitry Andric SDValue Load;
131904eeddc0SDimitry Andric if (UseGOT) {
132004eeddc0SDimitry Andric SDValue PICLabel = DAG.getTargetConstant(CSKYPCLabelIndex, DL, MVT::i32);
132104eeddc0SDimitry Andric auto *LRWGRS = DAG.getMachineNode(CSKY::PseudoTLSLA32, DL, {Ty, Ty},
132204eeddc0SDimitry Andric {CAddr, PICLabel});
132304eeddc0SDimitry Andric auto LRWADDGRS =
132404eeddc0SDimitry Andric DAG.getNode(ISD::ADD, DL, Ty, SDValue(LRWGRS, 0), SDValue(LRWGRS, 1));
132504eeddc0SDimitry Andric Load = DAG.getLoad(Ty, DL, DAG.getEntryNode(), LRWADDGRS,
132604eeddc0SDimitry Andric MachinePointerInfo(N->getGlobal()));
132704eeddc0SDimitry Andric } else {
132804eeddc0SDimitry Andric Load = SDValue(DAG.getMachineNode(CSKY::LRW32, DL, Ty, CAddr), 0);
132904eeddc0SDimitry Andric }
133004eeddc0SDimitry Andric
133104eeddc0SDimitry Andric // Add the thread pointer.
133204eeddc0SDimitry Andric SDValue TPReg = DAG.getRegister(CSKY::R31, MVT::i32);
133304eeddc0SDimitry Andric return DAG.getNode(ISD::ADD, DL, Ty, Load, TPReg);
133404eeddc0SDimitry Andric }
133504eeddc0SDimitry Andric
getDynamicTLSAddr(GlobalAddressSDNode * N,SelectionDAG & DAG) const133604eeddc0SDimitry Andric SDValue CSKYTargetLowering::getDynamicTLSAddr(GlobalAddressSDNode *N,
133704eeddc0SDimitry Andric SelectionDAG &DAG) const {
133804eeddc0SDimitry Andric MachineFunction &MF = DAG.getMachineFunction();
133904eeddc0SDimitry Andric CSKYMachineFunctionInfo *CFI = MF.getInfo<CSKYMachineFunctionInfo>();
134004eeddc0SDimitry Andric
134104eeddc0SDimitry Andric unsigned CSKYPCLabelIndex = CFI->createPICLabelUId();
134204eeddc0SDimitry Andric
134304eeddc0SDimitry Andric SDLoc DL(N);
134404eeddc0SDimitry Andric EVT Ty = getPointerTy(DAG.getDataLayout());
134504eeddc0SDimitry Andric IntegerType *CallTy = Type::getIntNTy(*DAG.getContext(), Ty.getSizeInBits());
134604eeddc0SDimitry Andric
134704eeddc0SDimitry Andric CSKYConstantPoolValue *CPV =
134804eeddc0SDimitry Andric CSKYConstantPoolConstant::Create(N->getGlobal(), CSKYCP::CPValue, 4,
134904eeddc0SDimitry Andric CSKYCP::TLSGD, true, CSKYPCLabelIndex);
135004eeddc0SDimitry Andric SDValue Addr = DAG.getTargetConstantPool(CPV, Ty);
135104eeddc0SDimitry Andric SDValue PICLabel = DAG.getTargetConstant(CSKYPCLabelIndex, DL, MVT::i32);
135204eeddc0SDimitry Andric
135304eeddc0SDimitry Andric auto *LRWGRS =
135404eeddc0SDimitry Andric DAG.getMachineNode(CSKY::PseudoTLSLA32, DL, {Ty, Ty}, {Addr, PICLabel});
135504eeddc0SDimitry Andric
135604eeddc0SDimitry Andric auto Load =
135704eeddc0SDimitry Andric DAG.getNode(ISD::ADD, DL, Ty, SDValue(LRWGRS, 0), SDValue(LRWGRS, 1));
135804eeddc0SDimitry Andric
135904eeddc0SDimitry Andric // Prepare argument list to generate call.
136004eeddc0SDimitry Andric ArgListTy Args;
136104eeddc0SDimitry Andric ArgListEntry Entry;
136204eeddc0SDimitry Andric Entry.Node = Load;
136304eeddc0SDimitry Andric Entry.Ty = CallTy;
136404eeddc0SDimitry Andric Args.push_back(Entry);
136504eeddc0SDimitry Andric
136604eeddc0SDimitry Andric // Setup call to __tls_get_addr.
136704eeddc0SDimitry Andric TargetLowering::CallLoweringInfo CLI(DAG);
136804eeddc0SDimitry Andric CLI.setDebugLoc(DL)
136904eeddc0SDimitry Andric .setChain(DAG.getEntryNode())
137004eeddc0SDimitry Andric .setLibCallee(CallingConv::C, CallTy,
137104eeddc0SDimitry Andric DAG.getExternalSymbol("__tls_get_addr", Ty),
137204eeddc0SDimitry Andric std::move(Args));
137304eeddc0SDimitry Andric SDValue V = LowerCallTo(CLI).first;
137404eeddc0SDimitry Andric
137504eeddc0SDimitry Andric return V;
137604eeddc0SDimitry Andric }
137706c3fb27SDimitry Andric
decomposeMulByConstant(LLVMContext & Context,EVT VT,SDValue C) const137806c3fb27SDimitry Andric bool CSKYTargetLowering::decomposeMulByConstant(LLVMContext &Context, EVT VT,
137906c3fb27SDimitry Andric SDValue C) const {
138006c3fb27SDimitry Andric if (!VT.isScalarInteger())
138106c3fb27SDimitry Andric return false;
138206c3fb27SDimitry Andric
138306c3fb27SDimitry Andric // Omit if data size exceeds.
138406c3fb27SDimitry Andric if (VT.getSizeInBits() > Subtarget.XLen)
138506c3fb27SDimitry Andric return false;
138606c3fb27SDimitry Andric
138706c3fb27SDimitry Andric if (auto *ConstNode = dyn_cast<ConstantSDNode>(C.getNode())) {
138806c3fb27SDimitry Andric const APInt &Imm = ConstNode->getAPIntValue();
138906c3fb27SDimitry Andric // Break MULT to LSLI + ADDU/SUBU.
139006c3fb27SDimitry Andric if ((Imm + 1).isPowerOf2() || (Imm - 1).isPowerOf2() ||
139106c3fb27SDimitry Andric (1 - Imm).isPowerOf2())
139206c3fb27SDimitry Andric return true;
139306c3fb27SDimitry Andric // Only break MULT for sub targets without MULT32, since an extra
139406c3fb27SDimitry Andric // instruction will be generated against the above 3 cases. We leave it
139506c3fb27SDimitry Andric // unchanged on sub targets with MULT32, since not sure it is better.
139606c3fb27SDimitry Andric if (!Subtarget.hasE2() && (-1 - Imm).isPowerOf2())
139706c3fb27SDimitry Andric return true;
13985f757f3fSDimitry Andric // Break (MULT x, imm) to ([IXH32|IXW32|IXD32] (LSLI32 x, i0), x) when
13995f757f3fSDimitry Andric // imm=(1<<i0)+[2|4|8] and imm has to be composed via a MOVIH32/ORI32 pair.
14005f757f3fSDimitry Andric if (Imm.ugt(0xffff) && ((Imm - 2).isPowerOf2() || (Imm - 4).isPowerOf2()) &&
14015f757f3fSDimitry Andric Subtarget.hasE2())
14025f757f3fSDimitry Andric return true;
14035f757f3fSDimitry Andric if (Imm.ugt(0xffff) && (Imm - 8).isPowerOf2() && Subtarget.has2E3())
14045f757f3fSDimitry Andric return true;
140506c3fb27SDimitry Andric }
140606c3fb27SDimitry Andric
140706c3fb27SDimitry Andric return false;
140806c3fb27SDimitry Andric }
14095f757f3fSDimitry Andric
isCheapToSpeculateCttz(Type * Ty) const14105f757f3fSDimitry Andric bool CSKYTargetLowering::isCheapToSpeculateCttz(Type *Ty) const {
14115f757f3fSDimitry Andric return Subtarget.has2E3();
14125f757f3fSDimitry Andric }
14135f757f3fSDimitry Andric
isCheapToSpeculateCtlz(Type * Ty) const14145f757f3fSDimitry Andric bool CSKYTargetLowering::isCheapToSpeculateCtlz(Type *Ty) const {
14155f757f3fSDimitry Andric return Subtarget.hasE2();
14165f757f3fSDimitry Andric }
1417