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 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 16504eeddc0SDimitry 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 191349cc55cSDimitry 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 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 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 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 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 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. 327349cc55cSDimitry 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 427349cc55cSDimitry 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 436349cc55cSDimitry 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. 50504eeddc0SDimitry 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, 55904eeddc0SDimitry Andric /*AlwaysInline=*/false, 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(); 65204eeddc0SDimitry Andric bool IsLocal = 65304eeddc0SDimitry Andric getTargetMachine().shouldAssumeDSOLocal(*GV->getParent(), GV); 65404eeddc0SDimitry Andric 65504eeddc0SDimitry Andric if (isPositionIndependent() || !Subtarget.has2E3()) { 65604eeddc0SDimitry Andric IsRegCall = true; 65704eeddc0SDimitry Andric Ops.push_back(getAddr<GlobalAddressSDNode, true>(S, DAG, IsLocal)); 65804eeddc0SDimitry Andric } else { 65904eeddc0SDimitry Andric Ops.push_back(getTargetNode(cast<GlobalAddressSDNode>(Callee), DL, Ty, 66004eeddc0SDimitry Andric DAG, CSKYII::MO_None)); 66104eeddc0SDimitry Andric Ops.push_back(getTargetConstantPoolValue( 66204eeddc0SDimitry Andric cast<GlobalAddressSDNode>(Callee), Ty, DAG, CSKYII::MO_None)); 66304eeddc0SDimitry Andric } 66404eeddc0SDimitry Andric } else if (ExternalSymbolSDNode *S = dyn_cast<ExternalSymbolSDNode>(Callee)) { 66504eeddc0SDimitry Andric bool IsLocal = getTargetMachine().shouldAssumeDSOLocal( 66604eeddc0SDimitry Andric *MF.getFunction().getParent(), nullptr); 66704eeddc0SDimitry Andric 66804eeddc0SDimitry Andric if (isPositionIndependent() || !Subtarget.has2E3()) { 66904eeddc0SDimitry Andric IsRegCall = true; 67004eeddc0SDimitry Andric Ops.push_back(getAddr<ExternalSymbolSDNode, true>(S, DAG, IsLocal)); 67104eeddc0SDimitry Andric } else { 67204eeddc0SDimitry Andric Ops.push_back(getTargetNode(cast<ExternalSymbolSDNode>(Callee), DL, Ty, 67304eeddc0SDimitry Andric DAG, CSKYII::MO_None)); 67404eeddc0SDimitry Andric Ops.push_back(getTargetConstantPoolValue( 67504eeddc0SDimitry Andric cast<ExternalSymbolSDNode>(Callee), Ty, DAG, CSKYII::MO_None)); 67604eeddc0SDimitry Andric } 67704eeddc0SDimitry Andric } else { 67804eeddc0SDimitry Andric IsRegCall = true; 67904eeddc0SDimitry Andric Ops.push_back(Callee); 68004eeddc0SDimitry Andric } 68104eeddc0SDimitry Andric 68204eeddc0SDimitry Andric // Add argument registers to the end of the list so that they are 68304eeddc0SDimitry Andric // known live into the call. 68404eeddc0SDimitry Andric for (auto &Reg : RegsToPass) 68504eeddc0SDimitry Andric Ops.push_back(DAG.getRegister(Reg.first, Reg.second.getValueType())); 68604eeddc0SDimitry Andric 68704eeddc0SDimitry Andric if (!IsTailCall) { 68804eeddc0SDimitry Andric // Add a register mask operand representing the call-preserved registers. 68904eeddc0SDimitry Andric const TargetRegisterInfo *TRI = Subtarget.getRegisterInfo(); 69004eeddc0SDimitry Andric const uint32_t *Mask = TRI->getCallPreservedMask(MF, CallConv); 69104eeddc0SDimitry Andric assert(Mask && "Missing call preserved mask for calling convention"); 69204eeddc0SDimitry Andric Ops.push_back(DAG.getRegisterMask(Mask)); 69304eeddc0SDimitry Andric } 69404eeddc0SDimitry Andric 69504eeddc0SDimitry Andric // Glue the call to the argument copies, if any. 69604eeddc0SDimitry Andric if (Glue.getNode()) 69704eeddc0SDimitry Andric Ops.push_back(Glue); 69804eeddc0SDimitry Andric 69904eeddc0SDimitry Andric // Emit the call. 70004eeddc0SDimitry Andric SDVTList NodeTys = DAG.getVTList(MVT::Other, MVT::Glue); 70104eeddc0SDimitry Andric 70204eeddc0SDimitry Andric if (IsTailCall) { 70304eeddc0SDimitry Andric MF.getFrameInfo().setHasTailCall(); 70404eeddc0SDimitry Andric return DAG.getNode(IsRegCall ? CSKYISD::TAILReg : CSKYISD::TAIL, DL, 70504eeddc0SDimitry Andric NodeTys, Ops); 70604eeddc0SDimitry Andric } 70704eeddc0SDimitry Andric 70804eeddc0SDimitry Andric Chain = DAG.getNode(IsRegCall ? CSKYISD::CALLReg : CSKYISD::CALL, DL, NodeTys, 70904eeddc0SDimitry Andric Ops); 71004eeddc0SDimitry Andric DAG.addNoMergeSiteInfo(Chain.getNode(), CLI.NoMerge); 71104eeddc0SDimitry Andric Glue = Chain.getValue(1); 71204eeddc0SDimitry Andric 71304eeddc0SDimitry Andric // Mark the end of the call, which is glued to the call itself. 714bdd1243dSDimitry Andric Chain = DAG.getCALLSEQ_END(Chain, NumBytes, 0, Glue, DL); 71504eeddc0SDimitry Andric Glue = Chain.getValue(1); 71604eeddc0SDimitry Andric 71704eeddc0SDimitry Andric // Assign locations to each value returned by this call. 71804eeddc0SDimitry Andric SmallVector<CCValAssign, 16> CSKYLocs; 71904eeddc0SDimitry Andric CCState RetCCInfo(CallConv, IsVarArg, MF, CSKYLocs, *DAG.getContext()); 72004eeddc0SDimitry Andric RetCCInfo.AnalyzeCallResult(Ins, CCAssignFnForReturn(CallConv, IsVarArg)); 72104eeddc0SDimitry Andric 72204eeddc0SDimitry Andric // Copy all of the result registers out of their specified physreg. 72304eeddc0SDimitry Andric for (auto &VA : CSKYLocs) { 72404eeddc0SDimitry Andric // Copy the value out 72504eeddc0SDimitry Andric SDValue RetValue = 72604eeddc0SDimitry Andric DAG.getCopyFromReg(Chain, DL, VA.getLocReg(), VA.getLocVT(), Glue); 72704eeddc0SDimitry Andric // Glue the RetValue to the end of the call sequence 72804eeddc0SDimitry Andric Chain = RetValue.getValue(1); 72904eeddc0SDimitry Andric Glue = RetValue.getValue(2); 73004eeddc0SDimitry Andric 73104eeddc0SDimitry Andric bool IsF64OnCSKY = VA.getLocVT() == MVT::i32 && VA.getValVT() == MVT::f64; 73204eeddc0SDimitry Andric 73304eeddc0SDimitry Andric if (IsF64OnCSKY) { 73404eeddc0SDimitry Andric assert(VA.getLocReg() == GPRArgRegs[0] && "Unexpected reg assignment"); 73504eeddc0SDimitry Andric SDValue RetValue2 = 73604eeddc0SDimitry Andric DAG.getCopyFromReg(Chain, DL, GPRArgRegs[1], MVT::i32, Glue); 73704eeddc0SDimitry Andric Chain = RetValue2.getValue(1); 73804eeddc0SDimitry Andric Glue = RetValue2.getValue(2); 73904eeddc0SDimitry Andric RetValue = DAG.getNode(CSKYISD::BITCAST_FROM_LOHI, DL, VA.getValVT(), 74004eeddc0SDimitry Andric RetValue, RetValue2); 74104eeddc0SDimitry Andric } 74204eeddc0SDimitry Andric 74304eeddc0SDimitry Andric RetValue = convertLocVTToValVT(DAG, RetValue, VA, DL); 74404eeddc0SDimitry Andric 74504eeddc0SDimitry Andric InVals.push_back(RetValue); 74604eeddc0SDimitry Andric } 74704eeddc0SDimitry Andric 74804eeddc0SDimitry Andric return Chain; 74904eeddc0SDimitry Andric } 75004eeddc0SDimitry Andric 751349cc55cSDimitry Andric CCAssignFn *CSKYTargetLowering::CCAssignFnForReturn(CallingConv::ID CC, 752349cc55cSDimitry Andric bool IsVarArg) const { 753349cc55cSDimitry Andric if (IsVarArg || !Subtarget.useHardFloatABI()) 754349cc55cSDimitry Andric return RetCC_CSKY_ABIV2_SOFT; 755349cc55cSDimitry Andric else 756349cc55cSDimitry Andric return RetCC_CSKY_ABIV2_FP; 757349cc55cSDimitry Andric } 758349cc55cSDimitry Andric 759349cc55cSDimitry Andric CCAssignFn *CSKYTargetLowering::CCAssignFnForCall(CallingConv::ID CC, 760349cc55cSDimitry Andric bool IsVarArg) const { 761349cc55cSDimitry Andric if (IsVarArg || !Subtarget.useHardFloatABI()) 762349cc55cSDimitry Andric return CC_CSKY_ABIV2_SOFT; 763349cc55cSDimitry Andric else 764349cc55cSDimitry Andric return CC_CSKY_ABIV2_FP; 765349cc55cSDimitry Andric } 766349cc55cSDimitry Andric 76704eeddc0SDimitry Andric static CSKYCP::CSKYCPModifier getModifier(unsigned Flags) { 76804eeddc0SDimitry Andric 76904eeddc0SDimitry Andric if (Flags == CSKYII::MO_ADDR32) 77004eeddc0SDimitry Andric return CSKYCP::ADDR; 77104eeddc0SDimitry Andric else if (Flags == CSKYII::MO_GOT32) 77204eeddc0SDimitry Andric return CSKYCP::GOT; 77304eeddc0SDimitry Andric else if (Flags == CSKYII::MO_GOTOFF) 77404eeddc0SDimitry Andric return CSKYCP::GOTOFF; 77504eeddc0SDimitry Andric else if (Flags == CSKYII::MO_PLT32) 77604eeddc0SDimitry Andric return CSKYCP::PLT; 77704eeddc0SDimitry Andric else if (Flags == CSKYII::MO_None) 77804eeddc0SDimitry Andric return CSKYCP::NO_MOD; 77904eeddc0SDimitry Andric else 78004eeddc0SDimitry Andric assert(0 && "unknown CSKYII Modifier"); 78104eeddc0SDimitry Andric return CSKYCP::NO_MOD; 78204eeddc0SDimitry Andric } 78304eeddc0SDimitry Andric 78404eeddc0SDimitry Andric SDValue CSKYTargetLowering::getTargetConstantPoolValue(GlobalAddressSDNode *N, 78504eeddc0SDimitry Andric EVT Ty, 78604eeddc0SDimitry Andric SelectionDAG &DAG, 78704eeddc0SDimitry Andric unsigned Flags) const { 78804eeddc0SDimitry Andric CSKYConstantPoolValue *CPV = CSKYConstantPoolConstant::Create( 78904eeddc0SDimitry Andric N->getGlobal(), CSKYCP::CPValue, 0, getModifier(Flags), false); 79004eeddc0SDimitry Andric 79104eeddc0SDimitry Andric return DAG.getTargetConstantPool(CPV, Ty); 79204eeddc0SDimitry Andric } 79304eeddc0SDimitry Andric 79481ad6265SDimitry Andric CSKYTargetLowering::ConstraintType 79581ad6265SDimitry Andric CSKYTargetLowering::getConstraintType(StringRef Constraint) const { 79681ad6265SDimitry Andric if (Constraint.size() == 1) { 79781ad6265SDimitry Andric switch (Constraint[0]) { 79881ad6265SDimitry Andric default: 79981ad6265SDimitry Andric break; 80081ad6265SDimitry Andric case 'a': 80181ad6265SDimitry Andric case 'b': 80281ad6265SDimitry Andric case 'v': 80381ad6265SDimitry Andric case 'w': 80481ad6265SDimitry Andric case 'y': 80581ad6265SDimitry Andric return C_RegisterClass; 80681ad6265SDimitry Andric case 'c': 80781ad6265SDimitry Andric case 'l': 80881ad6265SDimitry Andric case 'h': 80981ad6265SDimitry Andric case 'z': 81081ad6265SDimitry Andric return C_Register; 81181ad6265SDimitry Andric } 81281ad6265SDimitry Andric } 81381ad6265SDimitry Andric return TargetLowering::getConstraintType(Constraint); 81481ad6265SDimitry Andric } 81581ad6265SDimitry Andric 81681ad6265SDimitry Andric std::pair<unsigned, const TargetRegisterClass *> 81781ad6265SDimitry Andric CSKYTargetLowering::getRegForInlineAsmConstraint(const TargetRegisterInfo *TRI, 81881ad6265SDimitry Andric StringRef Constraint, 81981ad6265SDimitry Andric MVT VT) const { 82081ad6265SDimitry Andric if (Constraint.size() == 1) { 82181ad6265SDimitry Andric switch (Constraint[0]) { 82281ad6265SDimitry Andric case 'r': 82381ad6265SDimitry Andric return std::make_pair(0U, &CSKY::GPRRegClass); 82481ad6265SDimitry Andric case 'a': 82581ad6265SDimitry Andric return std::make_pair(0U, &CSKY::mGPRRegClass); 82681ad6265SDimitry Andric case 'b': 82781ad6265SDimitry Andric return std::make_pair(0U, &CSKY::sGPRRegClass); 82881ad6265SDimitry Andric case 'z': 82981ad6265SDimitry Andric return std::make_pair(CSKY::R14, &CSKY::GPRRegClass); 83081ad6265SDimitry Andric case 'c': 83181ad6265SDimitry Andric return std::make_pair(CSKY::C, &CSKY::CARRYRegClass); 83281ad6265SDimitry Andric case 'w': 83381ad6265SDimitry Andric if ((Subtarget.hasFPUv2SingleFloat() || 83481ad6265SDimitry Andric Subtarget.hasFPUv3SingleFloat()) && 83581ad6265SDimitry Andric VT == MVT::f32) 83681ad6265SDimitry Andric return std::make_pair(0U, &CSKY::sFPR32RegClass); 83781ad6265SDimitry Andric if ((Subtarget.hasFPUv2DoubleFloat() || 83881ad6265SDimitry Andric Subtarget.hasFPUv3DoubleFloat()) && 83981ad6265SDimitry Andric VT == MVT::f64) 84081ad6265SDimitry Andric return std::make_pair(0U, &CSKY::sFPR64RegClass); 84181ad6265SDimitry Andric break; 84281ad6265SDimitry Andric case 'v': 84381ad6265SDimitry Andric if (Subtarget.hasFPUv2SingleFloat() && VT == MVT::f32) 84481ad6265SDimitry Andric return std::make_pair(0U, &CSKY::sFPR32RegClass); 84581ad6265SDimitry Andric if (Subtarget.hasFPUv3SingleFloat() && VT == MVT::f32) 84681ad6265SDimitry Andric return std::make_pair(0U, &CSKY::FPR32RegClass); 84781ad6265SDimitry Andric if (Subtarget.hasFPUv2DoubleFloat() && VT == MVT::f64) 84881ad6265SDimitry Andric return std::make_pair(0U, &CSKY::sFPR64RegClass); 84981ad6265SDimitry Andric if (Subtarget.hasFPUv3DoubleFloat() && VT == MVT::f64) 85081ad6265SDimitry Andric return std::make_pair(0U, &CSKY::FPR64RegClass); 85181ad6265SDimitry Andric break; 85281ad6265SDimitry Andric default: 85381ad6265SDimitry Andric break; 85481ad6265SDimitry Andric } 85581ad6265SDimitry Andric } 85681ad6265SDimitry Andric 85781ad6265SDimitry Andric if (Constraint == "{c}") 85881ad6265SDimitry Andric return std::make_pair(CSKY::C, &CSKY::CARRYRegClass); 85981ad6265SDimitry Andric 86081ad6265SDimitry Andric // Clang will correctly decode the usage of register name aliases into their 86181ad6265SDimitry Andric // official names. However, other frontends like `rustc` do not. This allows 86281ad6265SDimitry Andric // users of these frontends to use the ABI names for registers in LLVM-style 86381ad6265SDimitry Andric // register constraints. 86481ad6265SDimitry Andric unsigned XRegFromAlias = StringSwitch<unsigned>(Constraint.lower()) 86581ad6265SDimitry Andric .Case("{a0}", CSKY::R0) 86681ad6265SDimitry Andric .Case("{a1}", CSKY::R1) 86781ad6265SDimitry Andric .Case("{a2}", CSKY::R2) 86881ad6265SDimitry Andric .Case("{a3}", CSKY::R3) 86981ad6265SDimitry Andric .Case("{l0}", CSKY::R4) 87081ad6265SDimitry Andric .Case("{l1}", CSKY::R5) 87181ad6265SDimitry Andric .Case("{l2}", CSKY::R6) 87281ad6265SDimitry Andric .Case("{l3}", CSKY::R7) 87381ad6265SDimitry Andric .Case("{l4}", CSKY::R8) 87481ad6265SDimitry Andric .Case("{l5}", CSKY::R9) 87581ad6265SDimitry Andric .Case("{l6}", CSKY::R10) 87681ad6265SDimitry Andric .Case("{l7}", CSKY::R11) 87781ad6265SDimitry Andric .Case("{t0}", CSKY::R12) 87881ad6265SDimitry Andric .Case("{t1}", CSKY::R13) 87981ad6265SDimitry Andric .Case("{sp}", CSKY::R14) 88081ad6265SDimitry Andric .Case("{lr}", CSKY::R15) 88181ad6265SDimitry Andric .Case("{l8}", CSKY::R16) 88281ad6265SDimitry Andric .Case("{l9}", CSKY::R17) 88381ad6265SDimitry Andric .Case("{t2}", CSKY::R18) 88481ad6265SDimitry Andric .Case("{t3}", CSKY::R19) 88581ad6265SDimitry Andric .Case("{t4}", CSKY::R20) 88681ad6265SDimitry Andric .Case("{t5}", CSKY::R21) 88781ad6265SDimitry Andric .Case("{t6}", CSKY::R22) 88881ad6265SDimitry Andric .Cases("{t7}", "{fp}", CSKY::R23) 88981ad6265SDimitry Andric .Cases("{t8}", "{top}", CSKY::R24) 89081ad6265SDimitry Andric .Cases("{t9}", "{bsp}", CSKY::R25) 89181ad6265SDimitry Andric .Case("{r26}", CSKY::R26) 89281ad6265SDimitry Andric .Case("{r27}", CSKY::R27) 89381ad6265SDimitry Andric .Cases("{gb}", "{rgb}", "{rdb}", CSKY::R28) 89481ad6265SDimitry Andric .Cases("{tb}", "{rtb}", CSKY::R29) 89581ad6265SDimitry Andric .Case("{svbr}", CSKY::R30) 89681ad6265SDimitry Andric .Case("{tls}", CSKY::R31) 89781ad6265SDimitry Andric .Default(CSKY::NoRegister); 89881ad6265SDimitry Andric 89981ad6265SDimitry Andric if (XRegFromAlias != CSKY::NoRegister) 90081ad6265SDimitry Andric return std::make_pair(XRegFromAlias, &CSKY::GPRRegClass); 90181ad6265SDimitry Andric 90281ad6265SDimitry Andric // Since TargetLowering::getRegForInlineAsmConstraint uses the name of the 90381ad6265SDimitry Andric // TableGen record rather than the AsmName to choose registers for InlineAsm 90481ad6265SDimitry Andric // constraints, plus we want to match those names to the widest floating point 90581ad6265SDimitry Andric // register type available, manually select floating point registers here. 90681ad6265SDimitry Andric // 90781ad6265SDimitry Andric // The second case is the ABI name of the register, so that frontends can also 90881ad6265SDimitry Andric // use the ABI names in register constraint lists. 90981ad6265SDimitry Andric if (Subtarget.useHardFloat()) { 91081ad6265SDimitry Andric unsigned FReg = StringSwitch<unsigned>(Constraint.lower()) 91181ad6265SDimitry Andric .Cases("{fr0}", "{vr0}", CSKY::F0_32) 91281ad6265SDimitry Andric .Cases("{fr1}", "{vr1}", CSKY::F1_32) 91381ad6265SDimitry Andric .Cases("{fr2}", "{vr2}", CSKY::F2_32) 91481ad6265SDimitry Andric .Cases("{fr3}", "{vr3}", CSKY::F3_32) 91581ad6265SDimitry Andric .Cases("{fr4}", "{vr4}", CSKY::F4_32) 91681ad6265SDimitry Andric .Cases("{fr5}", "{vr5}", CSKY::F5_32) 91781ad6265SDimitry Andric .Cases("{fr6}", "{vr6}", CSKY::F6_32) 91881ad6265SDimitry Andric .Cases("{fr7}", "{vr7}", CSKY::F7_32) 91981ad6265SDimitry Andric .Cases("{fr8}", "{vr8}", CSKY::F8_32) 92081ad6265SDimitry Andric .Cases("{fr9}", "{vr9}", CSKY::F9_32) 92181ad6265SDimitry Andric .Cases("{fr10}", "{vr10}", CSKY::F10_32) 92281ad6265SDimitry Andric .Cases("{fr11}", "{vr11}", CSKY::F11_32) 92381ad6265SDimitry Andric .Cases("{fr12}", "{vr12}", CSKY::F12_32) 92481ad6265SDimitry Andric .Cases("{fr13}", "{vr13}", CSKY::F13_32) 92581ad6265SDimitry Andric .Cases("{fr14}", "{vr14}", CSKY::F14_32) 92681ad6265SDimitry Andric .Cases("{fr15}", "{vr15}", CSKY::F15_32) 92781ad6265SDimitry Andric .Cases("{fr16}", "{vr16}", CSKY::F16_32) 92881ad6265SDimitry Andric .Cases("{fr17}", "{vr17}", CSKY::F17_32) 92981ad6265SDimitry Andric .Cases("{fr18}", "{vr18}", CSKY::F18_32) 93081ad6265SDimitry Andric .Cases("{fr19}", "{vr19}", CSKY::F19_32) 93181ad6265SDimitry Andric .Cases("{fr20}", "{vr20}", CSKY::F20_32) 93281ad6265SDimitry Andric .Cases("{fr21}", "{vr21}", CSKY::F21_32) 93381ad6265SDimitry Andric .Cases("{fr22}", "{vr22}", CSKY::F22_32) 93481ad6265SDimitry Andric .Cases("{fr23}", "{vr23}", CSKY::F23_32) 93581ad6265SDimitry Andric .Cases("{fr24}", "{vr24}", CSKY::F24_32) 93681ad6265SDimitry Andric .Cases("{fr25}", "{vr25}", CSKY::F25_32) 93781ad6265SDimitry Andric .Cases("{fr26}", "{vr26}", CSKY::F26_32) 93881ad6265SDimitry Andric .Cases("{fr27}", "{vr27}", CSKY::F27_32) 93981ad6265SDimitry Andric .Cases("{fr28}", "{vr28}", CSKY::F28_32) 94081ad6265SDimitry Andric .Cases("{fr29}", "{vr29}", CSKY::F29_32) 94181ad6265SDimitry Andric .Cases("{fr30}", "{vr30}", CSKY::F30_32) 94281ad6265SDimitry Andric .Cases("{fr31}", "{vr31}", CSKY::F31_32) 94381ad6265SDimitry Andric .Default(CSKY::NoRegister); 94481ad6265SDimitry Andric if (FReg != CSKY::NoRegister) { 94581ad6265SDimitry Andric assert(CSKY::F0_32 <= FReg && FReg <= CSKY::F31_32 && "Unknown fp-reg"); 94681ad6265SDimitry Andric unsigned RegNo = FReg - CSKY::F0_32; 94781ad6265SDimitry Andric unsigned DReg = CSKY::F0_64 + RegNo; 94881ad6265SDimitry Andric 94981ad6265SDimitry Andric if (Subtarget.hasFPUv2DoubleFloat()) 95081ad6265SDimitry Andric return std::make_pair(DReg, &CSKY::sFPR64RegClass); 95181ad6265SDimitry Andric else if (Subtarget.hasFPUv3DoubleFloat()) 95281ad6265SDimitry Andric return std::make_pair(DReg, &CSKY::FPR64RegClass); 95381ad6265SDimitry Andric else if (Subtarget.hasFPUv2SingleFloat()) 95481ad6265SDimitry Andric return std::make_pair(FReg, &CSKY::sFPR32RegClass); 95581ad6265SDimitry Andric else if (Subtarget.hasFPUv3SingleFloat()) 95681ad6265SDimitry Andric return std::make_pair(FReg, &CSKY::FPR32RegClass); 95781ad6265SDimitry Andric } 95881ad6265SDimitry Andric } 95981ad6265SDimitry Andric 96081ad6265SDimitry Andric return TargetLowering::getRegForInlineAsmConstraint(TRI, Constraint, VT); 96181ad6265SDimitry Andric } 96281ad6265SDimitry Andric 96304eeddc0SDimitry Andric static MachineBasicBlock * 96404eeddc0SDimitry Andric emitSelectPseudo(MachineInstr &MI, MachineBasicBlock *BB, unsigned Opcode) { 96504eeddc0SDimitry Andric 96604eeddc0SDimitry Andric const TargetInstrInfo &TII = *BB->getParent()->getSubtarget().getInstrInfo(); 96704eeddc0SDimitry Andric DebugLoc DL = MI.getDebugLoc(); 96804eeddc0SDimitry Andric 96904eeddc0SDimitry Andric // To "insert" a SELECT instruction, we actually have to insert the 97004eeddc0SDimitry Andric // diamond control-flow pattern. The incoming instruction knows the 97104eeddc0SDimitry Andric // destination vreg to set, the condition code register to branch on, the 97204eeddc0SDimitry Andric // true/false values to select between, and a branch opcode to use. 97304eeddc0SDimitry Andric const BasicBlock *LLVM_BB = BB->getBasicBlock(); 97404eeddc0SDimitry Andric MachineFunction::iterator It = ++BB->getIterator(); 97504eeddc0SDimitry Andric 97604eeddc0SDimitry Andric // thisMBB: 97704eeddc0SDimitry Andric // ... 97804eeddc0SDimitry Andric // TrueVal = ... 97904eeddc0SDimitry Andric // bt32 c, sinkMBB 98004eeddc0SDimitry Andric // fallthrough --> copyMBB 98104eeddc0SDimitry Andric MachineBasicBlock *thisMBB = BB; 98204eeddc0SDimitry Andric MachineFunction *F = BB->getParent(); 98304eeddc0SDimitry Andric MachineBasicBlock *copyMBB = F->CreateMachineBasicBlock(LLVM_BB); 98404eeddc0SDimitry Andric MachineBasicBlock *sinkMBB = F->CreateMachineBasicBlock(LLVM_BB); 98504eeddc0SDimitry Andric F->insert(It, copyMBB); 98604eeddc0SDimitry Andric F->insert(It, sinkMBB); 98704eeddc0SDimitry Andric 98804eeddc0SDimitry Andric // Transfer the remainder of BB and its successor edges to sinkMBB. 98904eeddc0SDimitry Andric sinkMBB->splice(sinkMBB->begin(), BB, 99004eeddc0SDimitry Andric std::next(MachineBasicBlock::iterator(MI)), BB->end()); 99104eeddc0SDimitry Andric sinkMBB->transferSuccessorsAndUpdatePHIs(BB); 99204eeddc0SDimitry Andric 99304eeddc0SDimitry Andric // Next, add the true and fallthrough blocks as its successors. 99404eeddc0SDimitry Andric BB->addSuccessor(copyMBB); 99504eeddc0SDimitry Andric BB->addSuccessor(sinkMBB); 99604eeddc0SDimitry Andric 99704eeddc0SDimitry Andric // bt32 condition, sinkMBB 99804eeddc0SDimitry Andric BuildMI(BB, DL, TII.get(Opcode)) 99904eeddc0SDimitry Andric .addReg(MI.getOperand(1).getReg()) 100004eeddc0SDimitry Andric .addMBB(sinkMBB); 100104eeddc0SDimitry Andric 100204eeddc0SDimitry Andric // copyMBB: 100304eeddc0SDimitry Andric // %FalseValue = ... 100404eeddc0SDimitry Andric // # fallthrough to sinkMBB 100504eeddc0SDimitry Andric BB = copyMBB; 100604eeddc0SDimitry Andric 100704eeddc0SDimitry Andric // Update machine-CFG edges 100804eeddc0SDimitry Andric BB->addSuccessor(sinkMBB); 100904eeddc0SDimitry Andric 101004eeddc0SDimitry Andric // sinkMBB: 101104eeddc0SDimitry Andric // %Result = phi [ %TrueValue, thisMBB ], [ %FalseValue, copyMBB ] 101204eeddc0SDimitry Andric // ... 101304eeddc0SDimitry Andric BB = sinkMBB; 101404eeddc0SDimitry Andric 101504eeddc0SDimitry Andric BuildMI(*BB, BB->begin(), DL, TII.get(CSKY::PHI), MI.getOperand(0).getReg()) 101604eeddc0SDimitry Andric .addReg(MI.getOperand(2).getReg()) 101704eeddc0SDimitry Andric .addMBB(thisMBB) 101804eeddc0SDimitry Andric .addReg(MI.getOperand(3).getReg()) 101904eeddc0SDimitry Andric .addMBB(copyMBB); 102004eeddc0SDimitry Andric 102104eeddc0SDimitry Andric MI.eraseFromParent(); // The pseudo instruction is gone now. 102204eeddc0SDimitry Andric 102304eeddc0SDimitry Andric return BB; 102404eeddc0SDimitry Andric } 102504eeddc0SDimitry Andric 102604eeddc0SDimitry Andric MachineBasicBlock * 102704eeddc0SDimitry Andric CSKYTargetLowering::EmitInstrWithCustomInserter(MachineInstr &MI, 102804eeddc0SDimitry Andric MachineBasicBlock *BB) const { 102904eeddc0SDimitry Andric switch (MI.getOpcode()) { 103004eeddc0SDimitry Andric default: 103104eeddc0SDimitry Andric llvm_unreachable("Unexpected instr type to insert"); 103281ad6265SDimitry Andric case CSKY::FSELS: 103381ad6265SDimitry Andric case CSKY::FSELD: 103481ad6265SDimitry Andric if (Subtarget.hasE2()) 103581ad6265SDimitry Andric return emitSelectPseudo(MI, BB, CSKY::BT32); 103681ad6265SDimitry Andric else 103781ad6265SDimitry Andric return emitSelectPseudo(MI, BB, CSKY::BT16); 103804eeddc0SDimitry Andric case CSKY::ISEL32: 103904eeddc0SDimitry Andric return emitSelectPseudo(MI, BB, CSKY::BT32); 104004eeddc0SDimitry Andric case CSKY::ISEL16: 104104eeddc0SDimitry Andric return emitSelectPseudo(MI, BB, CSKY::BT16); 104204eeddc0SDimitry Andric } 104304eeddc0SDimitry Andric } 104404eeddc0SDimitry Andric 104504eeddc0SDimitry Andric SDValue CSKYTargetLowering::getTargetConstantPoolValue(ExternalSymbolSDNode *N, 104604eeddc0SDimitry Andric EVT Ty, 104704eeddc0SDimitry Andric SelectionDAG &DAG, 104804eeddc0SDimitry Andric unsigned Flags) const { 104904eeddc0SDimitry Andric CSKYConstantPoolValue *CPV = 105004eeddc0SDimitry Andric CSKYConstantPoolSymbol::Create(Type::getInt32Ty(*DAG.getContext()), 105104eeddc0SDimitry Andric N->getSymbol(), 0, getModifier(Flags)); 105204eeddc0SDimitry Andric 105304eeddc0SDimitry Andric return DAG.getTargetConstantPool(CPV, Ty); 105404eeddc0SDimitry Andric } 105504eeddc0SDimitry Andric 105604eeddc0SDimitry Andric SDValue CSKYTargetLowering::getTargetConstantPoolValue(JumpTableSDNode *N, 105704eeddc0SDimitry Andric EVT Ty, 105804eeddc0SDimitry Andric SelectionDAG &DAG, 105904eeddc0SDimitry Andric unsigned Flags) const { 106004eeddc0SDimitry Andric CSKYConstantPoolValue *CPV = 106104eeddc0SDimitry Andric CSKYConstantPoolJT::Create(Type::getInt32Ty(*DAG.getContext()), 106204eeddc0SDimitry Andric N->getIndex(), 0, getModifier(Flags)); 106304eeddc0SDimitry Andric return DAG.getTargetConstantPool(CPV, Ty); 106404eeddc0SDimitry Andric } 106504eeddc0SDimitry Andric 106604eeddc0SDimitry Andric SDValue CSKYTargetLowering::getTargetConstantPoolValue(BlockAddressSDNode *N, 106704eeddc0SDimitry Andric EVT Ty, 106804eeddc0SDimitry Andric SelectionDAG &DAG, 106904eeddc0SDimitry Andric unsigned Flags) const { 1070bdd1243dSDimitry Andric assert(N->getOffset() == 0); 107104eeddc0SDimitry Andric CSKYConstantPoolValue *CPV = CSKYConstantPoolConstant::Create( 107204eeddc0SDimitry Andric N->getBlockAddress(), CSKYCP::CPBlockAddress, 0, getModifier(Flags), 107304eeddc0SDimitry Andric false); 107404eeddc0SDimitry Andric return DAG.getTargetConstantPool(CPV, Ty); 107504eeddc0SDimitry Andric } 107604eeddc0SDimitry Andric 1077bdd1243dSDimitry Andric SDValue CSKYTargetLowering::getTargetConstantPoolValue(ConstantPoolSDNode *N, 1078bdd1243dSDimitry Andric EVT Ty, 1079bdd1243dSDimitry Andric SelectionDAG &DAG, 1080bdd1243dSDimitry Andric unsigned Flags) const { 1081bdd1243dSDimitry Andric assert(N->getOffset() == 0); 1082bdd1243dSDimitry Andric CSKYConstantPoolValue *CPV = CSKYConstantPoolConstant::Create( 1083bdd1243dSDimitry Andric N->getConstVal(), Type::getInt32Ty(*DAG.getContext()), 1084bdd1243dSDimitry Andric CSKYCP::CPConstPool, 0, getModifier(Flags), false); 1085bdd1243dSDimitry Andric return DAG.getTargetConstantPool(CPV, Ty); 1086bdd1243dSDimitry Andric } 1087bdd1243dSDimitry Andric 108804eeddc0SDimitry Andric SDValue CSKYTargetLowering::getTargetNode(GlobalAddressSDNode *N, SDLoc DL, 108904eeddc0SDimitry Andric EVT Ty, SelectionDAG &DAG, 109004eeddc0SDimitry Andric unsigned Flags) const { 109104eeddc0SDimitry Andric return DAG.getTargetGlobalAddress(N->getGlobal(), DL, Ty, 0, Flags); 109204eeddc0SDimitry Andric } 109304eeddc0SDimitry Andric 109404eeddc0SDimitry Andric SDValue CSKYTargetLowering::getTargetNode(ExternalSymbolSDNode *N, SDLoc DL, 109504eeddc0SDimitry Andric EVT Ty, SelectionDAG &DAG, 109604eeddc0SDimitry Andric unsigned Flags) const { 109704eeddc0SDimitry Andric return DAG.getTargetExternalSymbol(N->getSymbol(), Ty, Flags); 109804eeddc0SDimitry Andric } 109904eeddc0SDimitry Andric 110004eeddc0SDimitry Andric SDValue CSKYTargetLowering::getTargetNode(JumpTableSDNode *N, SDLoc DL, EVT Ty, 110104eeddc0SDimitry Andric SelectionDAG &DAG, 110204eeddc0SDimitry Andric unsigned Flags) const { 110304eeddc0SDimitry Andric return DAG.getTargetJumpTable(N->getIndex(), Ty, Flags); 110404eeddc0SDimitry Andric } 110504eeddc0SDimitry Andric 110604eeddc0SDimitry Andric SDValue CSKYTargetLowering::getTargetNode(BlockAddressSDNode *N, SDLoc DL, 110704eeddc0SDimitry Andric EVT Ty, SelectionDAG &DAG, 110804eeddc0SDimitry Andric unsigned Flags) const { 110904eeddc0SDimitry Andric return DAG.getTargetBlockAddress(N->getBlockAddress(), Ty, N->getOffset(), 111004eeddc0SDimitry Andric Flags); 111104eeddc0SDimitry Andric } 111204eeddc0SDimitry Andric 1113bdd1243dSDimitry Andric SDValue CSKYTargetLowering::getTargetNode(ConstantPoolSDNode *N, SDLoc DL, 1114bdd1243dSDimitry Andric EVT Ty, SelectionDAG &DAG, 1115bdd1243dSDimitry Andric unsigned Flags) const { 1116bdd1243dSDimitry Andric 1117bdd1243dSDimitry Andric return DAG.getTargetConstantPool(N->getConstVal(), Ty, N->getAlign(), 1118bdd1243dSDimitry Andric N->getOffset(), Flags); 1119bdd1243dSDimitry Andric } 1120bdd1243dSDimitry Andric 1121349cc55cSDimitry Andric const char *CSKYTargetLowering::getTargetNodeName(unsigned Opcode) const { 1122349cc55cSDimitry Andric switch (Opcode) { 1123349cc55cSDimitry Andric default: 1124349cc55cSDimitry Andric llvm_unreachable("unknown CSKYISD node"); 1125349cc55cSDimitry Andric case CSKYISD::NIE: 1126349cc55cSDimitry Andric return "CSKYISD::NIE"; 1127349cc55cSDimitry Andric case CSKYISD::NIR: 1128349cc55cSDimitry Andric return "CSKYISD::NIR"; 1129349cc55cSDimitry Andric case CSKYISD::RET: 1130349cc55cSDimitry Andric return "CSKYISD::RET"; 113104eeddc0SDimitry Andric case CSKYISD::CALL: 113204eeddc0SDimitry Andric return "CSKYISD::CALL"; 113304eeddc0SDimitry Andric case CSKYISD::CALLReg: 113404eeddc0SDimitry Andric return "CSKYISD::CALLReg"; 113504eeddc0SDimitry Andric case CSKYISD::TAIL: 113604eeddc0SDimitry Andric return "CSKYISD::TAIL"; 113704eeddc0SDimitry Andric case CSKYISD::TAILReg: 113804eeddc0SDimitry Andric return "CSKYISD::TAILReg"; 113904eeddc0SDimitry Andric case CSKYISD::LOAD_ADDR: 114004eeddc0SDimitry Andric return "CSKYISD::LOAD_ADDR"; 1141349cc55cSDimitry Andric case CSKYISD::BITCAST_TO_LOHI: 1142349cc55cSDimitry Andric return "CSKYISD::BITCAST_TO_LOHI"; 114304eeddc0SDimitry Andric case CSKYISD::BITCAST_FROM_LOHI: 114404eeddc0SDimitry Andric return "CSKYISD::BITCAST_FROM_LOHI"; 1145349cc55cSDimitry Andric } 1146349cc55cSDimitry Andric } 114704eeddc0SDimitry Andric 114804eeddc0SDimitry Andric SDValue CSKYTargetLowering::LowerGlobalAddress(SDValue Op, 114904eeddc0SDimitry Andric SelectionDAG &DAG) const { 115004eeddc0SDimitry Andric SDLoc DL(Op); 115104eeddc0SDimitry Andric EVT Ty = Op.getValueType(); 115204eeddc0SDimitry Andric GlobalAddressSDNode *N = cast<GlobalAddressSDNode>(Op); 115304eeddc0SDimitry Andric int64_t Offset = N->getOffset(); 115404eeddc0SDimitry Andric 115504eeddc0SDimitry Andric const GlobalValue *GV = N->getGlobal(); 115604eeddc0SDimitry Andric bool IsLocal = getTargetMachine().shouldAssumeDSOLocal(*GV->getParent(), GV); 115704eeddc0SDimitry Andric SDValue Addr = getAddr<GlobalAddressSDNode, false>(N, DAG, IsLocal); 115804eeddc0SDimitry Andric 115904eeddc0SDimitry Andric // In order to maximise the opportunity for common subexpression elimination, 116004eeddc0SDimitry Andric // emit a separate ADD node for the global address offset instead of folding 116104eeddc0SDimitry Andric // it in the global address node. Later peephole optimisations may choose to 116204eeddc0SDimitry Andric // fold it back in when profitable. 116304eeddc0SDimitry Andric if (Offset != 0) 116404eeddc0SDimitry Andric return DAG.getNode(ISD::ADD, DL, Ty, Addr, 116504eeddc0SDimitry Andric DAG.getConstant(Offset, DL, MVT::i32)); 116604eeddc0SDimitry Andric return Addr; 116704eeddc0SDimitry Andric } 116804eeddc0SDimitry Andric 116904eeddc0SDimitry Andric SDValue CSKYTargetLowering::LowerExternalSymbol(SDValue Op, 117004eeddc0SDimitry Andric SelectionDAG &DAG) const { 117104eeddc0SDimitry Andric ExternalSymbolSDNode *N = cast<ExternalSymbolSDNode>(Op); 117204eeddc0SDimitry Andric 117304eeddc0SDimitry Andric return getAddr(N, DAG, false); 117404eeddc0SDimitry Andric } 117504eeddc0SDimitry Andric 117604eeddc0SDimitry Andric SDValue CSKYTargetLowering::LowerJumpTable(SDValue Op, 117704eeddc0SDimitry Andric SelectionDAG &DAG) const { 117804eeddc0SDimitry Andric JumpTableSDNode *N = cast<JumpTableSDNode>(Op); 117904eeddc0SDimitry Andric 118004eeddc0SDimitry Andric return getAddr<JumpTableSDNode, false>(N, DAG); 118104eeddc0SDimitry Andric } 118204eeddc0SDimitry Andric 118304eeddc0SDimitry Andric SDValue CSKYTargetLowering::LowerBlockAddress(SDValue Op, 118404eeddc0SDimitry Andric SelectionDAG &DAG) const { 118504eeddc0SDimitry Andric BlockAddressSDNode *N = cast<BlockAddressSDNode>(Op); 118604eeddc0SDimitry Andric 118704eeddc0SDimitry Andric return getAddr(N, DAG); 118804eeddc0SDimitry Andric } 118904eeddc0SDimitry Andric 1190bdd1243dSDimitry Andric SDValue CSKYTargetLowering::LowerConstantPool(SDValue Op, 1191bdd1243dSDimitry Andric SelectionDAG &DAG) const { 1192bdd1243dSDimitry Andric assert(!Subtarget.hasE2()); 1193bdd1243dSDimitry Andric ConstantPoolSDNode *N = cast<ConstantPoolSDNode>(Op); 1194bdd1243dSDimitry Andric 1195bdd1243dSDimitry Andric return getAddr(N, DAG); 1196bdd1243dSDimitry Andric } 1197bdd1243dSDimitry Andric 119804eeddc0SDimitry Andric SDValue CSKYTargetLowering::LowerVASTART(SDValue Op, SelectionDAG &DAG) const { 119904eeddc0SDimitry Andric MachineFunction &MF = DAG.getMachineFunction(); 120004eeddc0SDimitry Andric CSKYMachineFunctionInfo *FuncInfo = MF.getInfo<CSKYMachineFunctionInfo>(); 120104eeddc0SDimitry Andric 120204eeddc0SDimitry Andric SDLoc DL(Op); 120304eeddc0SDimitry Andric SDValue FI = DAG.getFrameIndex(FuncInfo->getVarArgsFrameIndex(), 120404eeddc0SDimitry Andric getPointerTy(MF.getDataLayout())); 120504eeddc0SDimitry Andric 120604eeddc0SDimitry Andric // vastart just stores the address of the VarArgsFrameIndex slot into the 120704eeddc0SDimitry Andric // memory location argument. 120804eeddc0SDimitry Andric const Value *SV = cast<SrcValueSDNode>(Op.getOperand(2))->getValue(); 120904eeddc0SDimitry Andric return DAG.getStore(Op.getOperand(0), DL, FI, Op.getOperand(1), 121004eeddc0SDimitry Andric MachinePointerInfo(SV)); 121104eeddc0SDimitry Andric } 121204eeddc0SDimitry Andric 121304eeddc0SDimitry Andric SDValue CSKYTargetLowering::LowerFRAMEADDR(SDValue Op, 121404eeddc0SDimitry Andric SelectionDAG &DAG) const { 121504eeddc0SDimitry Andric const CSKYRegisterInfo &RI = *Subtarget.getRegisterInfo(); 121604eeddc0SDimitry Andric MachineFunction &MF = DAG.getMachineFunction(); 121704eeddc0SDimitry Andric MachineFrameInfo &MFI = MF.getFrameInfo(); 121804eeddc0SDimitry Andric MFI.setFrameAddressIsTaken(true); 121904eeddc0SDimitry Andric 122004eeddc0SDimitry Andric EVT VT = Op.getValueType(); 122104eeddc0SDimitry Andric SDLoc dl(Op); 1222*647cbc5dSDimitry Andric unsigned Depth = Op.getConstantOperandVal(0); 122304eeddc0SDimitry Andric Register FrameReg = RI.getFrameRegister(MF); 122404eeddc0SDimitry Andric SDValue FrameAddr = DAG.getCopyFromReg(DAG.getEntryNode(), dl, FrameReg, VT); 122504eeddc0SDimitry Andric while (Depth--) 122604eeddc0SDimitry Andric FrameAddr = DAG.getLoad(VT, dl, DAG.getEntryNode(), FrameAddr, 122704eeddc0SDimitry Andric MachinePointerInfo()); 122804eeddc0SDimitry Andric return FrameAddr; 122904eeddc0SDimitry Andric } 123004eeddc0SDimitry Andric 123104eeddc0SDimitry Andric SDValue CSKYTargetLowering::LowerRETURNADDR(SDValue Op, 123204eeddc0SDimitry Andric SelectionDAG &DAG) const { 123304eeddc0SDimitry Andric const CSKYRegisterInfo &RI = *Subtarget.getRegisterInfo(); 123404eeddc0SDimitry Andric MachineFunction &MF = DAG.getMachineFunction(); 123504eeddc0SDimitry Andric MachineFrameInfo &MFI = MF.getFrameInfo(); 123604eeddc0SDimitry Andric MFI.setReturnAddressIsTaken(true); 123704eeddc0SDimitry Andric 123804eeddc0SDimitry Andric if (verifyReturnAddressArgumentIsConstant(Op, DAG)) 123904eeddc0SDimitry Andric return SDValue(); 124004eeddc0SDimitry Andric 124104eeddc0SDimitry Andric EVT VT = Op.getValueType(); 124204eeddc0SDimitry Andric SDLoc dl(Op); 1243*647cbc5dSDimitry Andric unsigned Depth = Op.getConstantOperandVal(0); 124404eeddc0SDimitry Andric if (Depth) { 124504eeddc0SDimitry Andric SDValue FrameAddr = LowerFRAMEADDR(Op, DAG); 124604eeddc0SDimitry Andric SDValue Offset = DAG.getConstant(4, dl, MVT::i32); 124704eeddc0SDimitry Andric return DAG.getLoad(VT, dl, DAG.getEntryNode(), 124804eeddc0SDimitry Andric DAG.getNode(ISD::ADD, dl, VT, FrameAddr, Offset), 124904eeddc0SDimitry Andric MachinePointerInfo()); 125004eeddc0SDimitry Andric } 125104eeddc0SDimitry Andric // Return the value of the return address register, marking it an implicit 125204eeddc0SDimitry Andric // live-in. 125304eeddc0SDimitry Andric unsigned Reg = MF.addLiveIn(RI.getRARegister(), getRegClassFor(MVT::i32)); 125404eeddc0SDimitry Andric return DAG.getCopyFromReg(DAG.getEntryNode(), dl, Reg, VT); 125504eeddc0SDimitry Andric } 125604eeddc0SDimitry Andric 125704eeddc0SDimitry Andric Register CSKYTargetLowering::getExceptionPointerRegister( 125804eeddc0SDimitry Andric const Constant *PersonalityFn) const { 125904eeddc0SDimitry Andric return CSKY::R0; 126004eeddc0SDimitry Andric } 126104eeddc0SDimitry Andric 126204eeddc0SDimitry Andric Register CSKYTargetLowering::getExceptionSelectorRegister( 126304eeddc0SDimitry Andric const Constant *PersonalityFn) const { 126404eeddc0SDimitry Andric return CSKY::R1; 126504eeddc0SDimitry Andric } 126604eeddc0SDimitry Andric 126704eeddc0SDimitry Andric SDValue CSKYTargetLowering::LowerGlobalTLSAddress(SDValue Op, 126804eeddc0SDimitry Andric SelectionDAG &DAG) const { 126904eeddc0SDimitry Andric SDLoc DL(Op); 127004eeddc0SDimitry Andric EVT Ty = Op.getValueType(); 127104eeddc0SDimitry Andric GlobalAddressSDNode *N = cast<GlobalAddressSDNode>(Op); 127204eeddc0SDimitry Andric int64_t Offset = N->getOffset(); 127304eeddc0SDimitry Andric MVT XLenVT = MVT::i32; 127404eeddc0SDimitry Andric 127504eeddc0SDimitry Andric TLSModel::Model Model = getTargetMachine().getTLSModel(N->getGlobal()); 127604eeddc0SDimitry Andric SDValue Addr; 127704eeddc0SDimitry Andric switch (Model) { 127804eeddc0SDimitry Andric case TLSModel::LocalExec: 127904eeddc0SDimitry Andric Addr = getStaticTLSAddr(N, DAG, /*UseGOT=*/false); 128004eeddc0SDimitry Andric break; 128104eeddc0SDimitry Andric case TLSModel::InitialExec: 128204eeddc0SDimitry Andric Addr = getStaticTLSAddr(N, DAG, /*UseGOT=*/true); 128304eeddc0SDimitry Andric break; 128404eeddc0SDimitry Andric case TLSModel::LocalDynamic: 128504eeddc0SDimitry Andric case TLSModel::GeneralDynamic: 128604eeddc0SDimitry Andric Addr = getDynamicTLSAddr(N, DAG); 128704eeddc0SDimitry Andric break; 128804eeddc0SDimitry Andric } 128904eeddc0SDimitry Andric 129004eeddc0SDimitry Andric // In order to maximise the opportunity for common subexpression elimination, 129104eeddc0SDimitry Andric // emit a separate ADD node for the global address offset instead of folding 129204eeddc0SDimitry Andric // it in the global address node. Later peephole optimisations may choose to 129304eeddc0SDimitry Andric // fold it back in when profitable. 129404eeddc0SDimitry Andric if (Offset != 0) 129504eeddc0SDimitry Andric return DAG.getNode(ISD::ADD, DL, Ty, Addr, 129604eeddc0SDimitry Andric DAG.getConstant(Offset, DL, XLenVT)); 129704eeddc0SDimitry Andric return Addr; 129804eeddc0SDimitry Andric } 129904eeddc0SDimitry Andric 130004eeddc0SDimitry Andric SDValue CSKYTargetLowering::getStaticTLSAddr(GlobalAddressSDNode *N, 130104eeddc0SDimitry Andric SelectionDAG &DAG, 130204eeddc0SDimitry Andric bool UseGOT) const { 130304eeddc0SDimitry Andric MachineFunction &MF = DAG.getMachineFunction(); 130404eeddc0SDimitry Andric CSKYMachineFunctionInfo *CFI = MF.getInfo<CSKYMachineFunctionInfo>(); 130504eeddc0SDimitry Andric 130604eeddc0SDimitry Andric unsigned CSKYPCLabelIndex = CFI->createPICLabelUId(); 130704eeddc0SDimitry Andric 130804eeddc0SDimitry Andric SDLoc DL(N); 130904eeddc0SDimitry Andric EVT Ty = getPointerTy(DAG.getDataLayout()); 131004eeddc0SDimitry Andric 131104eeddc0SDimitry Andric CSKYCP::CSKYCPModifier Flag = UseGOT ? CSKYCP::TLSIE : CSKYCP::TLSLE; 131204eeddc0SDimitry Andric bool AddCurrentAddr = UseGOT ? true : false; 131304eeddc0SDimitry Andric unsigned char PCAjust = UseGOT ? 4 : 0; 131404eeddc0SDimitry Andric 131504eeddc0SDimitry Andric CSKYConstantPoolValue *CPV = 131604eeddc0SDimitry Andric CSKYConstantPoolConstant::Create(N->getGlobal(), CSKYCP::CPValue, PCAjust, 131704eeddc0SDimitry Andric Flag, AddCurrentAddr, CSKYPCLabelIndex); 131804eeddc0SDimitry Andric SDValue CAddr = DAG.getTargetConstantPool(CPV, Ty); 131904eeddc0SDimitry Andric 132004eeddc0SDimitry Andric SDValue Load; 132104eeddc0SDimitry Andric if (UseGOT) { 132204eeddc0SDimitry Andric SDValue PICLabel = DAG.getTargetConstant(CSKYPCLabelIndex, DL, MVT::i32); 132304eeddc0SDimitry Andric auto *LRWGRS = DAG.getMachineNode(CSKY::PseudoTLSLA32, DL, {Ty, Ty}, 132404eeddc0SDimitry Andric {CAddr, PICLabel}); 132504eeddc0SDimitry Andric auto LRWADDGRS = 132604eeddc0SDimitry Andric DAG.getNode(ISD::ADD, DL, Ty, SDValue(LRWGRS, 0), SDValue(LRWGRS, 1)); 132704eeddc0SDimitry Andric Load = DAG.getLoad(Ty, DL, DAG.getEntryNode(), LRWADDGRS, 132804eeddc0SDimitry Andric MachinePointerInfo(N->getGlobal())); 132904eeddc0SDimitry Andric } else { 133004eeddc0SDimitry Andric Load = SDValue(DAG.getMachineNode(CSKY::LRW32, DL, Ty, CAddr), 0); 133104eeddc0SDimitry Andric } 133204eeddc0SDimitry Andric 133304eeddc0SDimitry Andric // Add the thread pointer. 133404eeddc0SDimitry Andric SDValue TPReg = DAG.getRegister(CSKY::R31, MVT::i32); 133504eeddc0SDimitry Andric return DAG.getNode(ISD::ADD, DL, Ty, Load, TPReg); 133604eeddc0SDimitry Andric } 133704eeddc0SDimitry Andric 133804eeddc0SDimitry Andric SDValue CSKYTargetLowering::getDynamicTLSAddr(GlobalAddressSDNode *N, 133904eeddc0SDimitry Andric SelectionDAG &DAG) const { 134004eeddc0SDimitry Andric MachineFunction &MF = DAG.getMachineFunction(); 134104eeddc0SDimitry Andric CSKYMachineFunctionInfo *CFI = MF.getInfo<CSKYMachineFunctionInfo>(); 134204eeddc0SDimitry Andric 134304eeddc0SDimitry Andric unsigned CSKYPCLabelIndex = CFI->createPICLabelUId(); 134404eeddc0SDimitry Andric 134504eeddc0SDimitry Andric SDLoc DL(N); 134604eeddc0SDimitry Andric EVT Ty = getPointerTy(DAG.getDataLayout()); 134704eeddc0SDimitry Andric IntegerType *CallTy = Type::getIntNTy(*DAG.getContext(), Ty.getSizeInBits()); 134804eeddc0SDimitry Andric 134904eeddc0SDimitry Andric CSKYConstantPoolValue *CPV = 135004eeddc0SDimitry Andric CSKYConstantPoolConstant::Create(N->getGlobal(), CSKYCP::CPValue, 4, 135104eeddc0SDimitry Andric CSKYCP::TLSGD, true, CSKYPCLabelIndex); 135204eeddc0SDimitry Andric SDValue Addr = DAG.getTargetConstantPool(CPV, Ty); 135304eeddc0SDimitry Andric SDValue PICLabel = DAG.getTargetConstant(CSKYPCLabelIndex, DL, MVT::i32); 135404eeddc0SDimitry Andric 135504eeddc0SDimitry Andric auto *LRWGRS = 135604eeddc0SDimitry Andric DAG.getMachineNode(CSKY::PseudoTLSLA32, DL, {Ty, Ty}, {Addr, PICLabel}); 135704eeddc0SDimitry Andric 135804eeddc0SDimitry Andric auto Load = 135904eeddc0SDimitry Andric DAG.getNode(ISD::ADD, DL, Ty, SDValue(LRWGRS, 0), SDValue(LRWGRS, 1)); 136004eeddc0SDimitry Andric 136104eeddc0SDimitry Andric // Prepare argument list to generate call. 136204eeddc0SDimitry Andric ArgListTy Args; 136304eeddc0SDimitry Andric ArgListEntry Entry; 136404eeddc0SDimitry Andric Entry.Node = Load; 136504eeddc0SDimitry Andric Entry.Ty = CallTy; 136604eeddc0SDimitry Andric Args.push_back(Entry); 136704eeddc0SDimitry Andric 136804eeddc0SDimitry Andric // Setup call to __tls_get_addr. 136904eeddc0SDimitry Andric TargetLowering::CallLoweringInfo CLI(DAG); 137004eeddc0SDimitry Andric CLI.setDebugLoc(DL) 137104eeddc0SDimitry Andric .setChain(DAG.getEntryNode()) 137204eeddc0SDimitry Andric .setLibCallee(CallingConv::C, CallTy, 137304eeddc0SDimitry Andric DAG.getExternalSymbol("__tls_get_addr", Ty), 137404eeddc0SDimitry Andric std::move(Args)); 137504eeddc0SDimitry Andric SDValue V = LowerCallTo(CLI).first; 137604eeddc0SDimitry Andric 137704eeddc0SDimitry Andric return V; 137804eeddc0SDimitry Andric } 137906c3fb27SDimitry Andric 138006c3fb27SDimitry Andric bool CSKYTargetLowering::decomposeMulByConstant(LLVMContext &Context, EVT VT, 138106c3fb27SDimitry Andric SDValue C) const { 138206c3fb27SDimitry Andric if (!VT.isScalarInteger()) 138306c3fb27SDimitry Andric return false; 138406c3fb27SDimitry Andric 138506c3fb27SDimitry Andric // Omit if data size exceeds. 138606c3fb27SDimitry Andric if (VT.getSizeInBits() > Subtarget.XLen) 138706c3fb27SDimitry Andric return false; 138806c3fb27SDimitry Andric 138906c3fb27SDimitry Andric if (auto *ConstNode = dyn_cast<ConstantSDNode>(C.getNode())) { 139006c3fb27SDimitry Andric const APInt &Imm = ConstNode->getAPIntValue(); 139106c3fb27SDimitry Andric // Break MULT to LSLI + ADDU/SUBU. 139206c3fb27SDimitry Andric if ((Imm + 1).isPowerOf2() || (Imm - 1).isPowerOf2() || 139306c3fb27SDimitry Andric (1 - Imm).isPowerOf2()) 139406c3fb27SDimitry Andric return true; 139506c3fb27SDimitry Andric // Only break MULT for sub targets without MULT32, since an extra 139606c3fb27SDimitry Andric // instruction will be generated against the above 3 cases. We leave it 139706c3fb27SDimitry Andric // unchanged on sub targets with MULT32, since not sure it is better. 139806c3fb27SDimitry Andric if (!Subtarget.hasE2() && (-1 - Imm).isPowerOf2()) 139906c3fb27SDimitry Andric return true; 14005f757f3fSDimitry Andric // Break (MULT x, imm) to ([IXH32|IXW32|IXD32] (LSLI32 x, i0), x) when 14015f757f3fSDimitry Andric // imm=(1<<i0)+[2|4|8] and imm has to be composed via a MOVIH32/ORI32 pair. 14025f757f3fSDimitry Andric if (Imm.ugt(0xffff) && ((Imm - 2).isPowerOf2() || (Imm - 4).isPowerOf2()) && 14035f757f3fSDimitry Andric Subtarget.hasE2()) 14045f757f3fSDimitry Andric return true; 14055f757f3fSDimitry Andric if (Imm.ugt(0xffff) && (Imm - 8).isPowerOf2() && Subtarget.has2E3()) 14065f757f3fSDimitry Andric return true; 140706c3fb27SDimitry Andric } 140806c3fb27SDimitry Andric 140906c3fb27SDimitry Andric return false; 141006c3fb27SDimitry Andric } 14115f757f3fSDimitry Andric 14125f757f3fSDimitry Andric bool CSKYTargetLowering::isCheapToSpeculateCttz(Type *Ty) const { 14135f757f3fSDimitry Andric return Subtarget.has2E3(); 14145f757f3fSDimitry Andric } 14155f757f3fSDimitry Andric 14165f757f3fSDimitry Andric bool CSKYTargetLowering::isCheapToSpeculateCtlz(Type *Ty) const { 14175f757f3fSDimitry Andric return Subtarget.hasE2(); 14185f757f3fSDimitry Andric } 1419