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