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, 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 749349cc55cSDimitry 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 757349cc55cSDimitry 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 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 78204eeddc0SDimitry 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 79381ad6265SDimitry 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 *> 81581ad6265SDimitry 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 * 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 * 102504eeddc0SDimitry 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 104304eeddc0SDimitry 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 105404eeddc0SDimitry 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 106404eeddc0SDimitry 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 1075bdd1243dSDimitry 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 108604eeddc0SDimitry 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 109204eeddc0SDimitry 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 109804eeddc0SDimitry 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 110404eeddc0SDimitry 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 1111bdd1243dSDimitry 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 1119349cc55cSDimitry 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 114604eeddc0SDimitry 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 116704eeddc0SDimitry 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 117404eeddc0SDimitry 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 118104eeddc0SDimitry 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 1188bdd1243dSDimitry 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 119604eeddc0SDimitry 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 121104eeddc0SDimitry 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 122904eeddc0SDimitry 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 125504eeddc0SDimitry Andric Register CSKYTargetLowering::getExceptionPointerRegister( 125604eeddc0SDimitry Andric const Constant *PersonalityFn) const { 125704eeddc0SDimitry Andric return CSKY::R0; 125804eeddc0SDimitry Andric } 125904eeddc0SDimitry Andric 126004eeddc0SDimitry Andric Register CSKYTargetLowering::getExceptionSelectorRegister( 126104eeddc0SDimitry Andric const Constant *PersonalityFn) const { 126204eeddc0SDimitry Andric return CSKY::R1; 126304eeddc0SDimitry Andric } 126404eeddc0SDimitry Andric 126504eeddc0SDimitry 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 129804eeddc0SDimitry 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 133604eeddc0SDimitry 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 137806c3fb27SDimitry 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 14105f757f3fSDimitry Andric bool CSKYTargetLowering::isCheapToSpeculateCttz(Type *Ty) const { 14115f757f3fSDimitry Andric return Subtarget.has2E3(); 14125f757f3fSDimitry Andric } 14135f757f3fSDimitry Andric 14145f757f3fSDimitry Andric bool CSKYTargetLowering::isCheapToSpeculateCtlz(Type *Ty) const { 14155f757f3fSDimitry Andric return Subtarget.hasE2(); 14165f757f3fSDimitry Andric } 1417