Path: blob/main/contrib/llvm-project/llvm/lib/Target/CSKY/CSKYISelLowering.cpp
35266 views
//===-- CSKYISelLowering.cpp - CSKY DAG Lowering Implementation ----------===//1//2// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.3// See https://llvm.org/LICENSE.txt for license information.4// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception5//6//===----------------------------------------------------------------------===//7//8// This file defines the interfaces that CSKY uses to lower LLVM code into a9// selection DAG.10//11//===----------------------------------------------------------------------===//1213#include "CSKYISelLowering.h"14#include "CSKYCallingConv.h"15#include "CSKYConstantPoolValue.h"16#include "CSKYMachineFunctionInfo.h"17#include "CSKYRegisterInfo.h"18#include "CSKYSubtarget.h"19#include "llvm/ADT/Statistic.h"20#include "llvm/CodeGen/CallingConvLower.h"21#include "llvm/CodeGen/MachineFrameInfo.h"22#include "llvm/CodeGen/MachineJumpTableInfo.h"23#include "llvm/Support/Debug.h"2425using namespace llvm;2627#define DEBUG_TYPE "csky-isel-lowering"2829STATISTIC(NumTailCalls, "Number of tail calls");3031#include "CSKYGenCallingConv.inc"3233static const MCPhysReg GPRArgRegs[] = {CSKY::R0, CSKY::R1, CSKY::R2, CSKY::R3};3435CSKYTargetLowering::CSKYTargetLowering(const TargetMachine &TM,36const CSKYSubtarget &STI)37: TargetLowering(TM), Subtarget(STI) {38// Register Class39addRegisterClass(MVT::i32, &CSKY::GPRRegClass);4041if (STI.useHardFloat()) {42if (STI.hasFPUv2SingleFloat())43addRegisterClass(MVT::f32, &CSKY::sFPR32RegClass);44else if (STI.hasFPUv3SingleFloat())45addRegisterClass(MVT::f32, &CSKY::FPR32RegClass);4647if (STI.hasFPUv2DoubleFloat())48addRegisterClass(MVT::f64, &CSKY::sFPR64RegClass);49else if (STI.hasFPUv3DoubleFloat())50addRegisterClass(MVT::f64, &CSKY::FPR64RegClass);51}5253setOperationAction(ISD::UADDO_CARRY, MVT::i32, Legal);54setOperationAction(ISD::USUBO_CARRY, MVT::i32, Legal);55setOperationAction(ISD::BITREVERSE, MVT::i32, Legal);5657setOperationAction(ISD::SREM, MVT::i32, Expand);58setOperationAction(ISD::UREM, MVT::i32, Expand);59setOperationAction(ISD::UDIVREM, MVT::i32, Expand);60setOperationAction(ISD::SDIVREM, MVT::i32, Expand);61setOperationAction(ISD::CTPOP, MVT::i32, Expand);62setOperationAction(ISD::ROTR, MVT::i32, Expand);63setOperationAction(ISD::SHL_PARTS, MVT::i32, Expand);64setOperationAction(ISD::SRL_PARTS, MVT::i32, Expand);65setOperationAction(ISD::SRA_PARTS, MVT::i32, Expand);66setOperationAction(ISD::UMUL_LOHI, MVT::i32, Expand);67setOperationAction(ISD::SMUL_LOHI, MVT::i32, Expand);68setOperationAction(ISD::SELECT_CC, MVT::i32, Expand);69setOperationAction(ISD::BR_CC, MVT::i32, Expand);70setOperationAction(ISD::BR_JT, MVT::Other, Expand);71setOperationAction(ISD::DYNAMIC_STACKALLOC, MVT::i32, Expand);72setOperationAction(ISD::STACKSAVE, MVT::Other, Expand);73setOperationAction(ISD::STACKRESTORE, MVT::Other, Expand);74setOperationAction(ISD::MULHS, MVT::i32, Expand);75setOperationAction(ISD::MULHU, MVT::i32, Expand);76setOperationAction(ISD::VAARG, MVT::Other, Expand);77setOperationAction(ISD::VACOPY, MVT::Other, Expand);78setOperationAction(ISD::VAEND, MVT::Other, Expand);7980setLoadExtAction(ISD::EXTLOAD, MVT::i32, MVT::i1, Promote);81setLoadExtAction(ISD::SEXTLOAD, MVT::i32, MVT::i1, Promote);82setLoadExtAction(ISD::ZEXTLOAD, MVT::i32, MVT::i1, Promote);8384setOperationAction(ISD::GlobalAddress, MVT::i32, Custom);85setOperationAction(ISD::ExternalSymbol, MVT::i32, Custom);86setOperationAction(ISD::GlobalTLSAddress, MVT::i32, Custom);87setOperationAction(ISD::BlockAddress, MVT::i32, Custom);88if (!Subtarget.hasE2()) {89setOperationAction(ISD::ConstantPool, MVT::i32, Custom);90}91setOperationAction(ISD::JumpTable, MVT::i32, Custom);92setOperationAction(ISD::VASTART, MVT::Other, Custom);9394if (!Subtarget.hasE2()) {95setLoadExtAction(ISD::SEXTLOAD, MVT::i32, MVT::i8, Expand);96setLoadExtAction(ISD::SEXTLOAD, MVT::i32, MVT::i16, Expand);97setOperationAction(ISD::CTLZ, MVT::i32, Expand);98setOperationAction(ISD::BSWAP, MVT::i32, Expand);99}100101if (!Subtarget.has2E3()) {102setOperationAction(ISD::ABS, MVT::i32, Expand);103setOperationAction(ISD::BITREVERSE, MVT::i32, Expand);104setOperationAction(ISD::CTTZ, MVT::i32, Expand);105setOperationAction(ISD::SDIV, MVT::i32, Expand);106setOperationAction(ISD::UDIV, MVT::i32, Expand);107}108109setOperationAction(ISD::ATOMIC_FENCE, MVT::Other, Expand);110111// Float112113ISD::CondCode FPCCToExtend[] = {114ISD::SETONE, ISD::SETUEQ, ISD::SETUGT,115ISD::SETUGE, ISD::SETULT, ISD::SETULE,116};117118ISD::NodeType FPOpToExpand[] = {119ISD::FSIN, ISD::FCOS, ISD::FSINCOS, ISD::FPOW,120ISD::FREM, ISD::FCOPYSIGN, ISD::FP16_TO_FP, ISD::FP_TO_FP16};121122if (STI.useHardFloat()) {123124MVT AllVTy[] = {MVT::f32, MVT::f64};125126for (auto VT : AllVTy) {127setOperationAction(ISD::FREM, VT, Expand);128setOperationAction(ISD::SELECT_CC, VT, Expand);129setOperationAction(ISD::BR_CC, VT, Expand);130131for (auto CC : FPCCToExtend)132setCondCodeAction(CC, VT, Expand);133for (auto Op : FPOpToExpand)134setOperationAction(Op, VT, Expand);135}136137if (STI.hasFPUv2SingleFloat() || STI.hasFPUv3SingleFloat()) {138setOperationAction(ISD::ConstantFP, MVT::f32, Legal);139setLoadExtAction(ISD::EXTLOAD, MVT::f32, MVT::f16, Expand);140setTruncStoreAction(MVT::f32, MVT::f16, Expand);141}142if (STI.hasFPUv2DoubleFloat() || STI.hasFPUv3DoubleFloat()) {143setLoadExtAction(ISD::EXTLOAD, MVT::f64, MVT::f32, Expand);144setTruncStoreAction(MVT::f64, MVT::f32, Expand);145setLoadExtAction(ISD::EXTLOAD, MVT::f64, MVT::f16, Expand);146setTruncStoreAction(MVT::f64, MVT::f16, Expand);147}148}149150// Compute derived properties from the register classes.151computeRegisterProperties(STI.getRegisterInfo());152153setBooleanContents(UndefinedBooleanContent);154setBooleanVectorContents(ZeroOrNegativeOneBooleanContent);155156// TODO: Add atomic support fully.157setMaxAtomicSizeInBitsSupported(0);158159setStackPointerRegisterToSaveRestore(CSKY::R14);160setMinFunctionAlignment(Align(2));161setSchedulingPreference(Sched::Source);162}163164SDValue CSKYTargetLowering::LowerOperation(SDValue Op,165SelectionDAG &DAG) const {166switch (Op.getOpcode()) {167default:168llvm_unreachable("unimplemented op");169case ISD::GlobalAddress:170return LowerGlobalAddress(Op, DAG);171case ISD::ExternalSymbol:172return LowerExternalSymbol(Op, DAG);173case ISD::GlobalTLSAddress:174return LowerGlobalTLSAddress(Op, DAG);175case ISD::JumpTable:176return LowerJumpTable(Op, DAG);177case ISD::BlockAddress:178return LowerBlockAddress(Op, DAG);179case ISD::ConstantPool:180return LowerConstantPool(Op, DAG);181case ISD::VASTART:182return LowerVASTART(Op, DAG);183case ISD::FRAMEADDR:184return LowerFRAMEADDR(Op, DAG);185case ISD::RETURNADDR:186return LowerRETURNADDR(Op, DAG);187}188}189190EVT CSKYTargetLowering::getSetCCResultType(const DataLayout &DL,191LLVMContext &Context, EVT VT) const {192if (!VT.isVector())193return MVT::i32;194195return VT.changeVectorElementTypeToInteger();196}197198static SDValue convertValVTToLocVT(SelectionDAG &DAG, SDValue Val,199const CCValAssign &VA, const SDLoc &DL) {200EVT LocVT = VA.getLocVT();201202switch (VA.getLocInfo()) {203default:204llvm_unreachable("Unexpected CCValAssign::LocInfo");205case CCValAssign::Full:206break;207case CCValAssign::BCvt:208Val = DAG.getNode(ISD::BITCAST, DL, LocVT, Val);209break;210}211return Val;212}213214static SDValue convertLocVTToValVT(SelectionDAG &DAG, SDValue Val,215const CCValAssign &VA, const SDLoc &DL) {216switch (VA.getLocInfo()) {217default:218llvm_unreachable("Unexpected CCValAssign::LocInfo");219case CCValAssign::Full:220break;221case CCValAssign::BCvt:222Val = DAG.getNode(ISD::BITCAST, DL, VA.getValVT(), Val);223break;224}225return Val;226}227228static SDValue unpackFromRegLoc(const CSKYSubtarget &Subtarget,229SelectionDAG &DAG, SDValue Chain,230const CCValAssign &VA, const SDLoc &DL) {231MachineFunction &MF = DAG.getMachineFunction();232MachineRegisterInfo &RegInfo = MF.getRegInfo();233EVT LocVT = VA.getLocVT();234SDValue Val;235const TargetRegisterClass *RC;236237switch (LocVT.getSimpleVT().SimpleTy) {238default:239llvm_unreachable("Unexpected register type");240case MVT::i32:241RC = &CSKY::GPRRegClass;242break;243case MVT::f32:244RC = Subtarget.hasFPUv2SingleFloat() ? &CSKY::sFPR32RegClass245: &CSKY::FPR32RegClass;246break;247case MVT::f64:248RC = Subtarget.hasFPUv2DoubleFloat() ? &CSKY::sFPR64RegClass249: &CSKY::FPR64RegClass;250break;251}252253Register VReg = RegInfo.createVirtualRegister(RC);254RegInfo.addLiveIn(VA.getLocReg(), VReg);255Val = DAG.getCopyFromReg(Chain, DL, VReg, LocVT);256257return convertLocVTToValVT(DAG, Val, VA, DL);258}259260static SDValue unpackFromMemLoc(SelectionDAG &DAG, SDValue Chain,261const CCValAssign &VA, const SDLoc &DL) {262MachineFunction &MF = DAG.getMachineFunction();263MachineFrameInfo &MFI = MF.getFrameInfo();264EVT LocVT = VA.getLocVT();265EVT ValVT = VA.getValVT();266EVT PtrVT = MVT::getIntegerVT(DAG.getDataLayout().getPointerSizeInBits(0));267int FI = MFI.CreateFixedObject(ValVT.getSizeInBits() / 8,268VA.getLocMemOffset(), /*Immutable=*/true);269SDValue FIN = DAG.getFrameIndex(FI, PtrVT);270SDValue Val;271272ISD::LoadExtType ExtType;273switch (VA.getLocInfo()) {274default:275llvm_unreachable("Unexpected CCValAssign::LocInfo");276case CCValAssign::Full:277case CCValAssign::BCvt:278ExtType = ISD::NON_EXTLOAD;279break;280}281Val = DAG.getExtLoad(282ExtType, DL, LocVT, Chain, FIN,283MachinePointerInfo::getFixedStack(DAG.getMachineFunction(), FI), ValVT);284return Val;285}286287static SDValue unpack64(SelectionDAG &DAG, SDValue Chain, const CCValAssign &VA,288const SDLoc &DL) {289assert(VA.getLocVT() == MVT::i32 &&290(VA.getValVT() == MVT::f64 || VA.getValVT() == MVT::i64) &&291"Unexpected VA");292MachineFunction &MF = DAG.getMachineFunction();293MachineFrameInfo &MFI = MF.getFrameInfo();294MachineRegisterInfo &RegInfo = MF.getRegInfo();295296if (VA.isMemLoc()) {297// f64/i64 is passed on the stack.298int FI = MFI.CreateFixedObject(8, VA.getLocMemOffset(), /*Immutable=*/true);299SDValue FIN = DAG.getFrameIndex(FI, MVT::i32);300return DAG.getLoad(VA.getValVT(), DL, Chain, FIN,301MachinePointerInfo::getFixedStack(MF, FI));302}303304assert(VA.isRegLoc() && "Expected register VA assignment");305306Register LoVReg = RegInfo.createVirtualRegister(&CSKY::GPRRegClass);307RegInfo.addLiveIn(VA.getLocReg(), LoVReg);308SDValue Lo = DAG.getCopyFromReg(Chain, DL, LoVReg, MVT::i32);309SDValue Hi;310if (VA.getLocReg() == CSKY::R3) {311// Second half of f64/i64 is passed on the stack.312int FI = MFI.CreateFixedObject(4, 0, /*Immutable=*/true);313SDValue FIN = DAG.getFrameIndex(FI, MVT::i32);314Hi = DAG.getLoad(MVT::i32, DL, Chain, FIN,315MachinePointerInfo::getFixedStack(MF, FI));316} else {317// Second half of f64/i64 is passed in another GPR.318Register HiVReg = RegInfo.createVirtualRegister(&CSKY::GPRRegClass);319RegInfo.addLiveIn(VA.getLocReg() + 1, HiVReg);320Hi = DAG.getCopyFromReg(Chain, DL, HiVReg, MVT::i32);321}322return DAG.getNode(CSKYISD::BITCAST_FROM_LOHI, DL, VA.getValVT(), Lo, Hi);323}324325// Transform physical registers into virtual registers.326SDValue CSKYTargetLowering::LowerFormalArguments(327SDValue Chain, CallingConv::ID CallConv, bool IsVarArg,328const SmallVectorImpl<ISD::InputArg> &Ins, const SDLoc &DL,329SelectionDAG &DAG, SmallVectorImpl<SDValue> &InVals) const {330331switch (CallConv) {332default:333report_fatal_error("Unsupported calling convention");334case CallingConv::C:335case CallingConv::Fast:336break;337}338339MachineFunction &MF = DAG.getMachineFunction();340341// Used with vargs to acumulate store chains.342std::vector<SDValue> OutChains;343344// Assign locations to all of the incoming arguments.345SmallVector<CCValAssign, 16> ArgLocs;346CCState CCInfo(CallConv, IsVarArg, MF, ArgLocs, *DAG.getContext());347348CCInfo.AnalyzeFormalArguments(Ins, CCAssignFnForCall(CallConv, IsVarArg));349350for (unsigned i = 0, e = ArgLocs.size(); i != e; ++i) {351CCValAssign &VA = ArgLocs[i];352SDValue ArgValue;353354bool IsF64OnCSKY = VA.getLocVT() == MVT::i32 && VA.getValVT() == MVT::f64;355356if (IsF64OnCSKY)357ArgValue = unpack64(DAG, Chain, VA, DL);358else if (VA.isRegLoc())359ArgValue = unpackFromRegLoc(Subtarget, DAG, Chain, VA, DL);360else361ArgValue = unpackFromMemLoc(DAG, Chain, VA, DL);362363InVals.push_back(ArgValue);364}365366if (IsVarArg) {367const unsigned XLenInBytes = 4;368const MVT XLenVT = MVT::i32;369370ArrayRef<MCPhysReg> ArgRegs = ArrayRef(GPRArgRegs);371unsigned Idx = CCInfo.getFirstUnallocated(ArgRegs);372const TargetRegisterClass *RC = &CSKY::GPRRegClass;373MachineFrameInfo &MFI = MF.getFrameInfo();374MachineRegisterInfo &RegInfo = MF.getRegInfo();375CSKYMachineFunctionInfo *CSKYFI = MF.getInfo<CSKYMachineFunctionInfo>();376377// Offset of the first variable argument from stack pointer, and size of378// the vararg save area. For now, the varargs save area is either zero or379// large enough to hold a0-a4.380int VaArgOffset, VarArgsSaveSize;381382// If all registers are allocated, then all varargs must be passed on the383// stack and we don't need to save any argregs.384if (ArgRegs.size() == Idx) {385VaArgOffset = CCInfo.getStackSize();386VarArgsSaveSize = 0;387} else {388VarArgsSaveSize = XLenInBytes * (ArgRegs.size() - Idx);389VaArgOffset = -VarArgsSaveSize;390}391392// Record the frame index of the first variable argument393// which is a value necessary to VASTART.394int FI = MFI.CreateFixedObject(XLenInBytes, VaArgOffset, true);395CSKYFI->setVarArgsFrameIndex(FI);396397// Copy the integer registers that may have been used for passing varargs398// to the vararg save area.399for (unsigned I = Idx; I < ArgRegs.size();400++I, VaArgOffset += XLenInBytes) {401const Register Reg = RegInfo.createVirtualRegister(RC);402RegInfo.addLiveIn(ArgRegs[I], Reg);403SDValue ArgValue = DAG.getCopyFromReg(Chain, DL, Reg, XLenVT);404FI = MFI.CreateFixedObject(XLenInBytes, VaArgOffset, true);405SDValue PtrOff = DAG.getFrameIndex(FI, getPointerTy(DAG.getDataLayout()));406SDValue Store = DAG.getStore(Chain, DL, ArgValue, PtrOff,407MachinePointerInfo::getFixedStack(MF, FI));408cast<StoreSDNode>(Store.getNode())409->getMemOperand()410->setValue((Value *)nullptr);411OutChains.push_back(Store);412}413CSKYFI->setVarArgsSaveSize(VarArgsSaveSize);414}415416// All stores are grouped in one node to allow the matching between417// the size of Ins and InVals. This only happens for vararg functions.418if (!OutChains.empty()) {419OutChains.push_back(Chain);420Chain = DAG.getNode(ISD::TokenFactor, DL, MVT::Other, OutChains);421}422423return Chain;424}425426bool CSKYTargetLowering::CanLowerReturn(427CallingConv::ID CallConv, MachineFunction &MF, bool IsVarArg,428const SmallVectorImpl<ISD::OutputArg> &Outs, LLVMContext &Context) const {429SmallVector<CCValAssign, 16> CSKYLocs;430CCState CCInfo(CallConv, IsVarArg, MF, CSKYLocs, Context);431return CCInfo.CheckReturn(Outs, CCAssignFnForReturn(CallConv, IsVarArg));432}433434SDValue435CSKYTargetLowering::LowerReturn(SDValue Chain, CallingConv::ID CallConv,436bool IsVarArg,437const SmallVectorImpl<ISD::OutputArg> &Outs,438const SmallVectorImpl<SDValue> &OutVals,439const SDLoc &DL, SelectionDAG &DAG) const {440// Stores the assignment of the return value to a location.441SmallVector<CCValAssign, 16> CSKYLocs;442443// Info about the registers and stack slot.444CCState CCInfo(CallConv, IsVarArg, DAG.getMachineFunction(), CSKYLocs,445*DAG.getContext());446CCInfo.AnalyzeReturn(Outs, CCAssignFnForReturn(CallConv, IsVarArg));447448SDValue Glue;449SmallVector<SDValue, 4> RetOps(1, Chain);450451// Copy the result values into the output registers.452for (unsigned i = 0, e = CSKYLocs.size(); i < e; ++i) {453SDValue Val = OutVals[i];454CCValAssign &VA = CSKYLocs[i];455assert(VA.isRegLoc() && "Can only return in registers!");456457bool IsF64OnCSKY = VA.getLocVT() == MVT::i32 && VA.getValVT() == MVT::f64;458459if (IsF64OnCSKY) {460461assert(VA.isRegLoc() && "Expected return via registers");462SDValue Split64 = DAG.getNode(CSKYISD::BITCAST_TO_LOHI, DL,463DAG.getVTList(MVT::i32, MVT::i32), Val);464SDValue Lo = Split64.getValue(0);465SDValue Hi = Split64.getValue(1);466467Register RegLo = VA.getLocReg();468assert(RegLo < CSKY::R31 && "Invalid register pair");469Register RegHi = RegLo + 1;470471Chain = DAG.getCopyToReg(Chain, DL, RegLo, Lo, Glue);472Glue = Chain.getValue(1);473RetOps.push_back(DAG.getRegister(RegLo, MVT::i32));474Chain = DAG.getCopyToReg(Chain, DL, RegHi, Hi, Glue);475Glue = Chain.getValue(1);476RetOps.push_back(DAG.getRegister(RegHi, MVT::i32));477} else {478// Handle a 'normal' return.479Val = convertValVTToLocVT(DAG, Val, VA, DL);480Chain = DAG.getCopyToReg(Chain, DL, VA.getLocReg(), Val, Glue);481482// Guarantee that all emitted copies are stuck together.483Glue = Chain.getValue(1);484RetOps.push_back(DAG.getRegister(VA.getLocReg(), VA.getLocVT()));485}486}487488RetOps[0] = Chain; // Update chain.489490// Add the glue node if we have it.491if (Glue.getNode()) {492RetOps.push_back(Glue);493}494495// Interrupt service routines use different return instructions.496if (DAG.getMachineFunction().getFunction().hasFnAttribute("interrupt"))497return DAG.getNode(CSKYISD::NIR, DL, MVT::Other, RetOps);498499return DAG.getNode(CSKYISD::RET, DL, MVT::Other, RetOps);500}501502// Lower a call to a callseq_start + CALL + callseq_end chain, and add input503// and output parameter nodes.504SDValue CSKYTargetLowering::LowerCall(CallLoweringInfo &CLI,505SmallVectorImpl<SDValue> &InVals) const {506SelectionDAG &DAG = CLI.DAG;507SDLoc &DL = CLI.DL;508SmallVectorImpl<ISD::OutputArg> &Outs = CLI.Outs;509SmallVectorImpl<SDValue> &OutVals = CLI.OutVals;510SmallVectorImpl<ISD::InputArg> &Ins = CLI.Ins;511SDValue Chain = CLI.Chain;512SDValue Callee = CLI.Callee;513bool &IsTailCall = CLI.IsTailCall;514CallingConv::ID CallConv = CLI.CallConv;515bool IsVarArg = CLI.IsVarArg;516EVT PtrVT = getPointerTy(DAG.getDataLayout());517MVT XLenVT = MVT::i32;518519MachineFunction &MF = DAG.getMachineFunction();520521// Analyze the operands of the call, assigning locations to each operand.522SmallVector<CCValAssign, 16> ArgLocs;523CCState ArgCCInfo(CallConv, IsVarArg, MF, ArgLocs, *DAG.getContext());524525ArgCCInfo.AnalyzeCallOperands(Outs, CCAssignFnForCall(CallConv, IsVarArg));526527// Check if it's really possible to do a tail call.528if (IsTailCall)529IsTailCall = false; // TODO: TailCallOptimization;530531if (IsTailCall)532++NumTailCalls;533else if (CLI.CB && CLI.CB->isMustTailCall())534report_fatal_error("failed to perform tail call elimination on a call "535"site marked musttail");536537// Get a count of how many bytes are to be pushed on the stack.538unsigned NumBytes = ArgCCInfo.getStackSize();539540// Create local copies for byval args541SmallVector<SDValue, 8> ByValArgs;542for (unsigned i = 0, e = Outs.size(); i != e; ++i) {543ISD::ArgFlagsTy Flags = Outs[i].Flags;544if (!Flags.isByVal())545continue;546547SDValue Arg = OutVals[i];548unsigned Size = Flags.getByValSize();549Align Alignment = Flags.getNonZeroByValAlign();550551int FI =552MF.getFrameInfo().CreateStackObject(Size, Alignment, /*isSS=*/false);553SDValue FIPtr = DAG.getFrameIndex(FI, getPointerTy(DAG.getDataLayout()));554SDValue SizeNode = DAG.getConstant(Size, DL, XLenVT);555556Chain = DAG.getMemcpy(Chain, DL, FIPtr, Arg, SizeNode, Alignment,557/*IsVolatile=*/false,558/*AlwaysInline=*/false, /*CI=*/nullptr, IsTailCall,559MachinePointerInfo(), MachinePointerInfo());560ByValArgs.push_back(FIPtr);561}562563if (!IsTailCall)564Chain = DAG.getCALLSEQ_START(Chain, NumBytes, 0, CLI.DL);565566// Copy argument values to their designated locations.567SmallVector<std::pair<Register, SDValue>, 8> RegsToPass;568SmallVector<SDValue, 8> MemOpChains;569SDValue StackPtr;570for (unsigned i = 0, j = 0, e = ArgLocs.size(); i != e; ++i) {571CCValAssign &VA = ArgLocs[i];572SDValue ArgValue = OutVals[i];573ISD::ArgFlagsTy Flags = Outs[i].Flags;574575bool IsF64OnCSKY = VA.getLocVT() == MVT::i32 && VA.getValVT() == MVT::f64;576577if (IsF64OnCSKY && VA.isRegLoc()) {578SDValue Split64 =579DAG.getNode(CSKYISD::BITCAST_TO_LOHI, DL,580DAG.getVTList(MVT::i32, MVT::i32), ArgValue);581SDValue Lo = Split64.getValue(0);582SDValue Hi = Split64.getValue(1);583584Register RegLo = VA.getLocReg();585RegsToPass.push_back(std::make_pair(RegLo, Lo));586587if (RegLo == CSKY::R3) {588// Second half of f64/i64 is passed on the stack.589// Work out the address of the stack slot.590if (!StackPtr.getNode())591StackPtr = DAG.getCopyFromReg(Chain, DL, CSKY::R14, PtrVT);592// Emit the store.593MemOpChains.push_back(594DAG.getStore(Chain, DL, Hi, StackPtr, MachinePointerInfo()));595} else {596// Second half of f64/i64 is passed in another GPR.597assert(RegLo < CSKY::R31 && "Invalid register pair");598Register RegHigh = RegLo + 1;599RegsToPass.push_back(std::make_pair(RegHigh, Hi));600}601continue;602}603604ArgValue = convertValVTToLocVT(DAG, ArgValue, VA, DL);605606// Use local copy if it is a byval arg.607if (Flags.isByVal())608ArgValue = ByValArgs[j++];609610if (VA.isRegLoc()) {611// Queue up the argument copies and emit them at the end.612RegsToPass.push_back(std::make_pair(VA.getLocReg(), ArgValue));613} else {614assert(VA.isMemLoc() && "Argument not register or memory");615assert(!IsTailCall && "Tail call not allowed if stack is used "616"for passing parameters");617618// Work out the address of the stack slot.619if (!StackPtr.getNode())620StackPtr = DAG.getCopyFromReg(Chain, DL, CSKY::R14, PtrVT);621SDValue Address =622DAG.getNode(ISD::ADD, DL, PtrVT, StackPtr,623DAG.getIntPtrConstant(VA.getLocMemOffset(), DL));624625// Emit the store.626MemOpChains.push_back(627DAG.getStore(Chain, DL, ArgValue, Address, MachinePointerInfo()));628}629}630631// Join the stores, which are independent of one another.632if (!MemOpChains.empty())633Chain = DAG.getNode(ISD::TokenFactor, DL, MVT::Other, MemOpChains);634635SDValue Glue;636637// Build a sequence of copy-to-reg nodes, chained and glued together.638for (auto &Reg : RegsToPass) {639Chain = DAG.getCopyToReg(Chain, DL, Reg.first, Reg.second, Glue);640Glue = Chain.getValue(1);641}642643SmallVector<SDValue, 8> Ops;644EVT Ty = getPointerTy(DAG.getDataLayout());645bool IsRegCall = false;646647Ops.push_back(Chain);648649if (GlobalAddressSDNode *S = dyn_cast<GlobalAddressSDNode>(Callee)) {650const GlobalValue *GV = S->getGlobal();651bool IsLocal = getTargetMachine().shouldAssumeDSOLocal(GV);652653if (isPositionIndependent() || !Subtarget.has2E3()) {654IsRegCall = true;655Ops.push_back(getAddr<GlobalAddressSDNode, true>(S, DAG, IsLocal));656} else {657Ops.push_back(getTargetNode(cast<GlobalAddressSDNode>(Callee), DL, Ty,658DAG, CSKYII::MO_None));659Ops.push_back(getTargetConstantPoolValue(660cast<GlobalAddressSDNode>(Callee), Ty, DAG, CSKYII::MO_None));661}662} else if (ExternalSymbolSDNode *S = dyn_cast<ExternalSymbolSDNode>(Callee)) {663bool IsLocal = getTargetMachine().shouldAssumeDSOLocal(nullptr);664665if (isPositionIndependent() || !Subtarget.has2E3()) {666IsRegCall = true;667Ops.push_back(getAddr<ExternalSymbolSDNode, true>(S, DAG, IsLocal));668} else {669Ops.push_back(getTargetNode(cast<ExternalSymbolSDNode>(Callee), DL, Ty,670DAG, CSKYII::MO_None));671Ops.push_back(getTargetConstantPoolValue(672cast<ExternalSymbolSDNode>(Callee), Ty, DAG, CSKYII::MO_None));673}674} else {675IsRegCall = true;676Ops.push_back(Callee);677}678679// Add argument registers to the end of the list so that they are680// known live into the call.681for (auto &Reg : RegsToPass)682Ops.push_back(DAG.getRegister(Reg.first, Reg.second.getValueType()));683684if (!IsTailCall) {685// Add a register mask operand representing the call-preserved registers.686const TargetRegisterInfo *TRI = Subtarget.getRegisterInfo();687const uint32_t *Mask = TRI->getCallPreservedMask(MF, CallConv);688assert(Mask && "Missing call preserved mask for calling convention");689Ops.push_back(DAG.getRegisterMask(Mask));690}691692// Glue the call to the argument copies, if any.693if (Glue.getNode())694Ops.push_back(Glue);695696// Emit the call.697SDVTList NodeTys = DAG.getVTList(MVT::Other, MVT::Glue);698699if (IsTailCall) {700MF.getFrameInfo().setHasTailCall();701return DAG.getNode(IsRegCall ? CSKYISD::TAILReg : CSKYISD::TAIL, DL,702NodeTys, Ops);703}704705Chain = DAG.getNode(IsRegCall ? CSKYISD::CALLReg : CSKYISD::CALL, DL, NodeTys,706Ops);707DAG.addNoMergeSiteInfo(Chain.getNode(), CLI.NoMerge);708Glue = Chain.getValue(1);709710// Mark the end of the call, which is glued to the call itself.711Chain = DAG.getCALLSEQ_END(Chain, NumBytes, 0, Glue, DL);712Glue = Chain.getValue(1);713714// Assign locations to each value returned by this call.715SmallVector<CCValAssign, 16> CSKYLocs;716CCState RetCCInfo(CallConv, IsVarArg, MF, CSKYLocs, *DAG.getContext());717RetCCInfo.AnalyzeCallResult(Ins, CCAssignFnForReturn(CallConv, IsVarArg));718719// Copy all of the result registers out of their specified physreg.720for (auto &VA : CSKYLocs) {721// Copy the value out722SDValue RetValue =723DAG.getCopyFromReg(Chain, DL, VA.getLocReg(), VA.getLocVT(), Glue);724// Glue the RetValue to the end of the call sequence725Chain = RetValue.getValue(1);726Glue = RetValue.getValue(2);727728bool IsF64OnCSKY = VA.getLocVT() == MVT::i32 && VA.getValVT() == MVT::f64;729730if (IsF64OnCSKY) {731assert(VA.getLocReg() == GPRArgRegs[0] && "Unexpected reg assignment");732SDValue RetValue2 =733DAG.getCopyFromReg(Chain, DL, GPRArgRegs[1], MVT::i32, Glue);734Chain = RetValue2.getValue(1);735Glue = RetValue2.getValue(2);736RetValue = DAG.getNode(CSKYISD::BITCAST_FROM_LOHI, DL, VA.getValVT(),737RetValue, RetValue2);738}739740RetValue = convertLocVTToValVT(DAG, RetValue, VA, DL);741742InVals.push_back(RetValue);743}744745return Chain;746}747748CCAssignFn *CSKYTargetLowering::CCAssignFnForReturn(CallingConv::ID CC,749bool IsVarArg) const {750if (IsVarArg || !Subtarget.useHardFloatABI())751return RetCC_CSKY_ABIV2_SOFT;752else753return RetCC_CSKY_ABIV2_FP;754}755756CCAssignFn *CSKYTargetLowering::CCAssignFnForCall(CallingConv::ID CC,757bool IsVarArg) const {758if (IsVarArg || !Subtarget.useHardFloatABI())759return CC_CSKY_ABIV2_SOFT;760else761return CC_CSKY_ABIV2_FP;762}763764static CSKYCP::CSKYCPModifier getModifier(unsigned Flags) {765766if (Flags == CSKYII::MO_ADDR32)767return CSKYCP::ADDR;768else if (Flags == CSKYII::MO_GOT32)769return CSKYCP::GOT;770else if (Flags == CSKYII::MO_GOTOFF)771return CSKYCP::GOTOFF;772else if (Flags == CSKYII::MO_PLT32)773return CSKYCP::PLT;774else if (Flags == CSKYII::MO_None)775return CSKYCP::NO_MOD;776else777assert(0 && "unknown CSKYII Modifier");778return CSKYCP::NO_MOD;779}780781SDValue CSKYTargetLowering::getTargetConstantPoolValue(GlobalAddressSDNode *N,782EVT Ty,783SelectionDAG &DAG,784unsigned Flags) const {785CSKYConstantPoolValue *CPV = CSKYConstantPoolConstant::Create(786N->getGlobal(), CSKYCP::CPValue, 0, getModifier(Flags), false);787788return DAG.getTargetConstantPool(CPV, Ty);789}790791CSKYTargetLowering::ConstraintType792CSKYTargetLowering::getConstraintType(StringRef Constraint) const {793if (Constraint.size() == 1) {794switch (Constraint[0]) {795default:796break;797case 'a':798case 'b':799case 'v':800case 'w':801case 'y':802return C_RegisterClass;803case 'c':804case 'l':805case 'h':806case 'z':807return C_Register;808}809}810return TargetLowering::getConstraintType(Constraint);811}812813std::pair<unsigned, const TargetRegisterClass *>814CSKYTargetLowering::getRegForInlineAsmConstraint(const TargetRegisterInfo *TRI,815StringRef Constraint,816MVT VT) const {817if (Constraint.size() == 1) {818switch (Constraint[0]) {819case 'r':820return std::make_pair(0U, &CSKY::GPRRegClass);821case 'a':822return std::make_pair(0U, &CSKY::mGPRRegClass);823case 'b':824return std::make_pair(0U, &CSKY::sGPRRegClass);825case 'z':826return std::make_pair(CSKY::R14, &CSKY::GPRRegClass);827case 'c':828return std::make_pair(CSKY::C, &CSKY::CARRYRegClass);829case 'w':830if ((Subtarget.hasFPUv2SingleFloat() ||831Subtarget.hasFPUv3SingleFloat()) &&832VT == MVT::f32)833return std::make_pair(0U, &CSKY::sFPR32RegClass);834if ((Subtarget.hasFPUv2DoubleFloat() ||835Subtarget.hasFPUv3DoubleFloat()) &&836VT == MVT::f64)837return std::make_pair(0U, &CSKY::sFPR64RegClass);838break;839case 'v':840if (Subtarget.hasFPUv2SingleFloat() && VT == MVT::f32)841return std::make_pair(0U, &CSKY::sFPR32RegClass);842if (Subtarget.hasFPUv3SingleFloat() && VT == MVT::f32)843return std::make_pair(0U, &CSKY::FPR32RegClass);844if (Subtarget.hasFPUv2DoubleFloat() && VT == MVT::f64)845return std::make_pair(0U, &CSKY::sFPR64RegClass);846if (Subtarget.hasFPUv3DoubleFloat() && VT == MVT::f64)847return std::make_pair(0U, &CSKY::FPR64RegClass);848break;849default:850break;851}852}853854if (Constraint == "{c}")855return std::make_pair(CSKY::C, &CSKY::CARRYRegClass);856857// Clang will correctly decode the usage of register name aliases into their858// official names. However, other frontends like `rustc` do not. This allows859// users of these frontends to use the ABI names for registers in LLVM-style860// register constraints.861unsigned XRegFromAlias = StringSwitch<unsigned>(Constraint.lower())862.Case("{a0}", CSKY::R0)863.Case("{a1}", CSKY::R1)864.Case("{a2}", CSKY::R2)865.Case("{a3}", CSKY::R3)866.Case("{l0}", CSKY::R4)867.Case("{l1}", CSKY::R5)868.Case("{l2}", CSKY::R6)869.Case("{l3}", CSKY::R7)870.Case("{l4}", CSKY::R8)871.Case("{l5}", CSKY::R9)872.Case("{l6}", CSKY::R10)873.Case("{l7}", CSKY::R11)874.Case("{t0}", CSKY::R12)875.Case("{t1}", CSKY::R13)876.Case("{sp}", CSKY::R14)877.Case("{lr}", CSKY::R15)878.Case("{l8}", CSKY::R16)879.Case("{l9}", CSKY::R17)880.Case("{t2}", CSKY::R18)881.Case("{t3}", CSKY::R19)882.Case("{t4}", CSKY::R20)883.Case("{t5}", CSKY::R21)884.Case("{t6}", CSKY::R22)885.Cases("{t7}", "{fp}", CSKY::R23)886.Cases("{t8}", "{top}", CSKY::R24)887.Cases("{t9}", "{bsp}", CSKY::R25)888.Case("{r26}", CSKY::R26)889.Case("{r27}", CSKY::R27)890.Cases("{gb}", "{rgb}", "{rdb}", CSKY::R28)891.Cases("{tb}", "{rtb}", CSKY::R29)892.Case("{svbr}", CSKY::R30)893.Case("{tls}", CSKY::R31)894.Default(CSKY::NoRegister);895896if (XRegFromAlias != CSKY::NoRegister)897return std::make_pair(XRegFromAlias, &CSKY::GPRRegClass);898899// Since TargetLowering::getRegForInlineAsmConstraint uses the name of the900// TableGen record rather than the AsmName to choose registers for InlineAsm901// constraints, plus we want to match those names to the widest floating point902// register type available, manually select floating point registers here.903//904// The second case is the ABI name of the register, so that frontends can also905// use the ABI names in register constraint lists.906if (Subtarget.useHardFloat()) {907unsigned FReg = StringSwitch<unsigned>(Constraint.lower())908.Cases("{fr0}", "{vr0}", CSKY::F0_32)909.Cases("{fr1}", "{vr1}", CSKY::F1_32)910.Cases("{fr2}", "{vr2}", CSKY::F2_32)911.Cases("{fr3}", "{vr3}", CSKY::F3_32)912.Cases("{fr4}", "{vr4}", CSKY::F4_32)913.Cases("{fr5}", "{vr5}", CSKY::F5_32)914.Cases("{fr6}", "{vr6}", CSKY::F6_32)915.Cases("{fr7}", "{vr7}", CSKY::F7_32)916.Cases("{fr8}", "{vr8}", CSKY::F8_32)917.Cases("{fr9}", "{vr9}", CSKY::F9_32)918.Cases("{fr10}", "{vr10}", CSKY::F10_32)919.Cases("{fr11}", "{vr11}", CSKY::F11_32)920.Cases("{fr12}", "{vr12}", CSKY::F12_32)921.Cases("{fr13}", "{vr13}", CSKY::F13_32)922.Cases("{fr14}", "{vr14}", CSKY::F14_32)923.Cases("{fr15}", "{vr15}", CSKY::F15_32)924.Cases("{fr16}", "{vr16}", CSKY::F16_32)925.Cases("{fr17}", "{vr17}", CSKY::F17_32)926.Cases("{fr18}", "{vr18}", CSKY::F18_32)927.Cases("{fr19}", "{vr19}", CSKY::F19_32)928.Cases("{fr20}", "{vr20}", CSKY::F20_32)929.Cases("{fr21}", "{vr21}", CSKY::F21_32)930.Cases("{fr22}", "{vr22}", CSKY::F22_32)931.Cases("{fr23}", "{vr23}", CSKY::F23_32)932.Cases("{fr24}", "{vr24}", CSKY::F24_32)933.Cases("{fr25}", "{vr25}", CSKY::F25_32)934.Cases("{fr26}", "{vr26}", CSKY::F26_32)935.Cases("{fr27}", "{vr27}", CSKY::F27_32)936.Cases("{fr28}", "{vr28}", CSKY::F28_32)937.Cases("{fr29}", "{vr29}", CSKY::F29_32)938.Cases("{fr30}", "{vr30}", CSKY::F30_32)939.Cases("{fr31}", "{vr31}", CSKY::F31_32)940.Default(CSKY::NoRegister);941if (FReg != CSKY::NoRegister) {942assert(CSKY::F0_32 <= FReg && FReg <= CSKY::F31_32 && "Unknown fp-reg");943unsigned RegNo = FReg - CSKY::F0_32;944unsigned DReg = CSKY::F0_64 + RegNo;945946if (Subtarget.hasFPUv2DoubleFloat())947return std::make_pair(DReg, &CSKY::sFPR64RegClass);948else if (Subtarget.hasFPUv3DoubleFloat())949return std::make_pair(DReg, &CSKY::FPR64RegClass);950else if (Subtarget.hasFPUv2SingleFloat())951return std::make_pair(FReg, &CSKY::sFPR32RegClass);952else if (Subtarget.hasFPUv3SingleFloat())953return std::make_pair(FReg, &CSKY::FPR32RegClass);954}955}956957return TargetLowering::getRegForInlineAsmConstraint(TRI, Constraint, VT);958}959960static MachineBasicBlock *961emitSelectPseudo(MachineInstr &MI, MachineBasicBlock *BB, unsigned Opcode) {962963const TargetInstrInfo &TII = *BB->getParent()->getSubtarget().getInstrInfo();964DebugLoc DL = MI.getDebugLoc();965966// To "insert" a SELECT instruction, we actually have to insert the967// diamond control-flow pattern. The incoming instruction knows the968// destination vreg to set, the condition code register to branch on, the969// true/false values to select between, and a branch opcode to use.970const BasicBlock *LLVM_BB = BB->getBasicBlock();971MachineFunction::iterator It = ++BB->getIterator();972973// thisMBB:974// ...975// TrueVal = ...976// bt32 c, sinkMBB977// fallthrough --> copyMBB978MachineBasicBlock *thisMBB = BB;979MachineFunction *F = BB->getParent();980MachineBasicBlock *copyMBB = F->CreateMachineBasicBlock(LLVM_BB);981MachineBasicBlock *sinkMBB = F->CreateMachineBasicBlock(LLVM_BB);982F->insert(It, copyMBB);983F->insert(It, sinkMBB);984985// Transfer the remainder of BB and its successor edges to sinkMBB.986sinkMBB->splice(sinkMBB->begin(), BB,987std::next(MachineBasicBlock::iterator(MI)), BB->end());988sinkMBB->transferSuccessorsAndUpdatePHIs(BB);989990// Next, add the true and fallthrough blocks as its successors.991BB->addSuccessor(copyMBB);992BB->addSuccessor(sinkMBB);993994// bt32 condition, sinkMBB995BuildMI(BB, DL, TII.get(Opcode))996.addReg(MI.getOperand(1).getReg())997.addMBB(sinkMBB);998999// copyMBB:1000// %FalseValue = ...1001// # fallthrough to sinkMBB1002BB = copyMBB;10031004// Update machine-CFG edges1005BB->addSuccessor(sinkMBB);10061007// sinkMBB:1008// %Result = phi [ %TrueValue, thisMBB ], [ %FalseValue, copyMBB ]1009// ...1010BB = sinkMBB;10111012BuildMI(*BB, BB->begin(), DL, TII.get(CSKY::PHI), MI.getOperand(0).getReg())1013.addReg(MI.getOperand(2).getReg())1014.addMBB(thisMBB)1015.addReg(MI.getOperand(3).getReg())1016.addMBB(copyMBB);10171018MI.eraseFromParent(); // The pseudo instruction is gone now.10191020return BB;1021}10221023MachineBasicBlock *1024CSKYTargetLowering::EmitInstrWithCustomInserter(MachineInstr &MI,1025MachineBasicBlock *BB) const {1026switch (MI.getOpcode()) {1027default:1028llvm_unreachable("Unexpected instr type to insert");1029case CSKY::FSELS:1030case CSKY::FSELD:1031if (Subtarget.hasE2())1032return emitSelectPseudo(MI, BB, CSKY::BT32);1033else1034return emitSelectPseudo(MI, BB, CSKY::BT16);1035case CSKY::ISEL32:1036return emitSelectPseudo(MI, BB, CSKY::BT32);1037case CSKY::ISEL16:1038return emitSelectPseudo(MI, BB, CSKY::BT16);1039}1040}10411042SDValue CSKYTargetLowering::getTargetConstantPoolValue(ExternalSymbolSDNode *N,1043EVT Ty,1044SelectionDAG &DAG,1045unsigned Flags) const {1046CSKYConstantPoolValue *CPV =1047CSKYConstantPoolSymbol::Create(Type::getInt32Ty(*DAG.getContext()),1048N->getSymbol(), 0, getModifier(Flags));10491050return DAG.getTargetConstantPool(CPV, Ty);1051}10521053SDValue CSKYTargetLowering::getTargetConstantPoolValue(JumpTableSDNode *N,1054EVT Ty,1055SelectionDAG &DAG,1056unsigned Flags) const {1057CSKYConstantPoolValue *CPV =1058CSKYConstantPoolJT::Create(Type::getInt32Ty(*DAG.getContext()),1059N->getIndex(), 0, getModifier(Flags));1060return DAG.getTargetConstantPool(CPV, Ty);1061}10621063SDValue CSKYTargetLowering::getTargetConstantPoolValue(BlockAddressSDNode *N,1064EVT Ty,1065SelectionDAG &DAG,1066unsigned Flags) const {1067assert(N->getOffset() == 0);1068CSKYConstantPoolValue *CPV = CSKYConstantPoolConstant::Create(1069N->getBlockAddress(), CSKYCP::CPBlockAddress, 0, getModifier(Flags),1070false);1071return DAG.getTargetConstantPool(CPV, Ty);1072}10731074SDValue CSKYTargetLowering::getTargetConstantPoolValue(ConstantPoolSDNode *N,1075EVT Ty,1076SelectionDAG &DAG,1077unsigned Flags) const {1078assert(N->getOffset() == 0);1079CSKYConstantPoolValue *CPV = CSKYConstantPoolConstant::Create(1080N->getConstVal(), Type::getInt32Ty(*DAG.getContext()),1081CSKYCP::CPConstPool, 0, getModifier(Flags), false);1082return DAG.getTargetConstantPool(CPV, Ty);1083}10841085SDValue CSKYTargetLowering::getTargetNode(GlobalAddressSDNode *N, SDLoc DL,1086EVT Ty, SelectionDAG &DAG,1087unsigned Flags) const {1088return DAG.getTargetGlobalAddress(N->getGlobal(), DL, Ty, 0, Flags);1089}10901091SDValue CSKYTargetLowering::getTargetNode(ExternalSymbolSDNode *N, SDLoc DL,1092EVT Ty, SelectionDAG &DAG,1093unsigned Flags) const {1094return DAG.getTargetExternalSymbol(N->getSymbol(), Ty, Flags);1095}10961097SDValue CSKYTargetLowering::getTargetNode(JumpTableSDNode *N, SDLoc DL, EVT Ty,1098SelectionDAG &DAG,1099unsigned Flags) const {1100return DAG.getTargetJumpTable(N->getIndex(), Ty, Flags);1101}11021103SDValue CSKYTargetLowering::getTargetNode(BlockAddressSDNode *N, SDLoc DL,1104EVT Ty, SelectionDAG &DAG,1105unsigned Flags) const {1106return DAG.getTargetBlockAddress(N->getBlockAddress(), Ty, N->getOffset(),1107Flags);1108}11091110SDValue CSKYTargetLowering::getTargetNode(ConstantPoolSDNode *N, SDLoc DL,1111EVT Ty, SelectionDAG &DAG,1112unsigned Flags) const {11131114return DAG.getTargetConstantPool(N->getConstVal(), Ty, N->getAlign(),1115N->getOffset(), Flags);1116}11171118const char *CSKYTargetLowering::getTargetNodeName(unsigned Opcode) const {1119switch (Opcode) {1120default:1121llvm_unreachable("unknown CSKYISD node");1122case CSKYISD::NIE:1123return "CSKYISD::NIE";1124case CSKYISD::NIR:1125return "CSKYISD::NIR";1126case CSKYISD::RET:1127return "CSKYISD::RET";1128case CSKYISD::CALL:1129return "CSKYISD::CALL";1130case CSKYISD::CALLReg:1131return "CSKYISD::CALLReg";1132case CSKYISD::TAIL:1133return "CSKYISD::TAIL";1134case CSKYISD::TAILReg:1135return "CSKYISD::TAILReg";1136case CSKYISD::LOAD_ADDR:1137return "CSKYISD::LOAD_ADDR";1138case CSKYISD::BITCAST_TO_LOHI:1139return "CSKYISD::BITCAST_TO_LOHI";1140case CSKYISD::BITCAST_FROM_LOHI:1141return "CSKYISD::BITCAST_FROM_LOHI";1142}1143}11441145SDValue CSKYTargetLowering::LowerGlobalAddress(SDValue Op,1146SelectionDAG &DAG) const {1147SDLoc DL(Op);1148EVT Ty = Op.getValueType();1149GlobalAddressSDNode *N = cast<GlobalAddressSDNode>(Op);1150int64_t Offset = N->getOffset();11511152const GlobalValue *GV = N->getGlobal();1153bool IsLocal = getTargetMachine().shouldAssumeDSOLocal(GV);1154SDValue Addr = getAddr<GlobalAddressSDNode, false>(N, DAG, IsLocal);11551156// In order to maximise the opportunity for common subexpression elimination,1157// emit a separate ADD node for the global address offset instead of folding1158// it in the global address node. Later peephole optimisations may choose to1159// fold it back in when profitable.1160if (Offset != 0)1161return DAG.getNode(ISD::ADD, DL, Ty, Addr,1162DAG.getConstant(Offset, DL, MVT::i32));1163return Addr;1164}11651166SDValue CSKYTargetLowering::LowerExternalSymbol(SDValue Op,1167SelectionDAG &DAG) const {1168ExternalSymbolSDNode *N = cast<ExternalSymbolSDNode>(Op);11691170return getAddr(N, DAG, false);1171}11721173SDValue CSKYTargetLowering::LowerJumpTable(SDValue Op,1174SelectionDAG &DAG) const {1175JumpTableSDNode *N = cast<JumpTableSDNode>(Op);11761177return getAddr<JumpTableSDNode, false>(N, DAG);1178}11791180SDValue CSKYTargetLowering::LowerBlockAddress(SDValue Op,1181SelectionDAG &DAG) const {1182BlockAddressSDNode *N = cast<BlockAddressSDNode>(Op);11831184return getAddr(N, DAG);1185}11861187SDValue CSKYTargetLowering::LowerConstantPool(SDValue Op,1188SelectionDAG &DAG) const {1189assert(!Subtarget.hasE2());1190ConstantPoolSDNode *N = cast<ConstantPoolSDNode>(Op);11911192return getAddr(N, DAG);1193}11941195SDValue CSKYTargetLowering::LowerVASTART(SDValue Op, SelectionDAG &DAG) const {1196MachineFunction &MF = DAG.getMachineFunction();1197CSKYMachineFunctionInfo *FuncInfo = MF.getInfo<CSKYMachineFunctionInfo>();11981199SDLoc DL(Op);1200SDValue FI = DAG.getFrameIndex(FuncInfo->getVarArgsFrameIndex(),1201getPointerTy(MF.getDataLayout()));12021203// vastart just stores the address of the VarArgsFrameIndex slot into the1204// memory location argument.1205const Value *SV = cast<SrcValueSDNode>(Op.getOperand(2))->getValue();1206return DAG.getStore(Op.getOperand(0), DL, FI, Op.getOperand(1),1207MachinePointerInfo(SV));1208}12091210SDValue CSKYTargetLowering::LowerFRAMEADDR(SDValue Op,1211SelectionDAG &DAG) const {1212const CSKYRegisterInfo &RI = *Subtarget.getRegisterInfo();1213MachineFunction &MF = DAG.getMachineFunction();1214MachineFrameInfo &MFI = MF.getFrameInfo();1215MFI.setFrameAddressIsTaken(true);12161217EVT VT = Op.getValueType();1218SDLoc dl(Op);1219unsigned Depth = Op.getConstantOperandVal(0);1220Register FrameReg = RI.getFrameRegister(MF);1221SDValue FrameAddr = DAG.getCopyFromReg(DAG.getEntryNode(), dl, FrameReg, VT);1222while (Depth--)1223FrameAddr = DAG.getLoad(VT, dl, DAG.getEntryNode(), FrameAddr,1224MachinePointerInfo());1225return FrameAddr;1226}12271228SDValue CSKYTargetLowering::LowerRETURNADDR(SDValue Op,1229SelectionDAG &DAG) const {1230const CSKYRegisterInfo &RI = *Subtarget.getRegisterInfo();1231MachineFunction &MF = DAG.getMachineFunction();1232MachineFrameInfo &MFI = MF.getFrameInfo();1233MFI.setReturnAddressIsTaken(true);12341235if (verifyReturnAddressArgumentIsConstant(Op, DAG))1236return SDValue();12371238EVT VT = Op.getValueType();1239SDLoc dl(Op);1240unsigned Depth = Op.getConstantOperandVal(0);1241if (Depth) {1242SDValue FrameAddr = LowerFRAMEADDR(Op, DAG);1243SDValue Offset = DAG.getConstant(4, dl, MVT::i32);1244return DAG.getLoad(VT, dl, DAG.getEntryNode(),1245DAG.getNode(ISD::ADD, dl, VT, FrameAddr, Offset),1246MachinePointerInfo());1247}1248// Return the value of the return address register, marking it an implicit1249// live-in.1250unsigned Reg = MF.addLiveIn(RI.getRARegister(), getRegClassFor(MVT::i32));1251return DAG.getCopyFromReg(DAG.getEntryNode(), dl, Reg, VT);1252}12531254Register CSKYTargetLowering::getExceptionPointerRegister(1255const Constant *PersonalityFn) const {1256return CSKY::R0;1257}12581259Register CSKYTargetLowering::getExceptionSelectorRegister(1260const Constant *PersonalityFn) const {1261return CSKY::R1;1262}12631264SDValue CSKYTargetLowering::LowerGlobalTLSAddress(SDValue Op,1265SelectionDAG &DAG) const {1266SDLoc DL(Op);1267EVT Ty = Op.getValueType();1268GlobalAddressSDNode *N = cast<GlobalAddressSDNode>(Op);1269int64_t Offset = N->getOffset();1270MVT XLenVT = MVT::i32;12711272TLSModel::Model Model = getTargetMachine().getTLSModel(N->getGlobal());1273SDValue Addr;1274switch (Model) {1275case TLSModel::LocalExec:1276Addr = getStaticTLSAddr(N, DAG, /*UseGOT=*/false);1277break;1278case TLSModel::InitialExec:1279Addr = getStaticTLSAddr(N, DAG, /*UseGOT=*/true);1280break;1281case TLSModel::LocalDynamic:1282case TLSModel::GeneralDynamic:1283Addr = getDynamicTLSAddr(N, DAG);1284break;1285}12861287// In order to maximise the opportunity for common subexpression elimination,1288// emit a separate ADD node for the global address offset instead of folding1289// it in the global address node. Later peephole optimisations may choose to1290// fold it back in when profitable.1291if (Offset != 0)1292return DAG.getNode(ISD::ADD, DL, Ty, Addr,1293DAG.getConstant(Offset, DL, XLenVT));1294return Addr;1295}12961297SDValue CSKYTargetLowering::getStaticTLSAddr(GlobalAddressSDNode *N,1298SelectionDAG &DAG,1299bool UseGOT) const {1300MachineFunction &MF = DAG.getMachineFunction();1301CSKYMachineFunctionInfo *CFI = MF.getInfo<CSKYMachineFunctionInfo>();13021303unsigned CSKYPCLabelIndex = CFI->createPICLabelUId();13041305SDLoc DL(N);1306EVT Ty = getPointerTy(DAG.getDataLayout());13071308CSKYCP::CSKYCPModifier Flag = UseGOT ? CSKYCP::TLSIE : CSKYCP::TLSLE;1309bool AddCurrentAddr = UseGOT ? true : false;1310unsigned char PCAjust = UseGOT ? 4 : 0;13111312CSKYConstantPoolValue *CPV =1313CSKYConstantPoolConstant::Create(N->getGlobal(), CSKYCP::CPValue, PCAjust,1314Flag, AddCurrentAddr, CSKYPCLabelIndex);1315SDValue CAddr = DAG.getTargetConstantPool(CPV, Ty);13161317SDValue Load;1318if (UseGOT) {1319SDValue PICLabel = DAG.getTargetConstant(CSKYPCLabelIndex, DL, MVT::i32);1320auto *LRWGRS = DAG.getMachineNode(CSKY::PseudoTLSLA32, DL, {Ty, Ty},1321{CAddr, PICLabel});1322auto LRWADDGRS =1323DAG.getNode(ISD::ADD, DL, Ty, SDValue(LRWGRS, 0), SDValue(LRWGRS, 1));1324Load = DAG.getLoad(Ty, DL, DAG.getEntryNode(), LRWADDGRS,1325MachinePointerInfo(N->getGlobal()));1326} else {1327Load = SDValue(DAG.getMachineNode(CSKY::LRW32, DL, Ty, CAddr), 0);1328}13291330// Add the thread pointer.1331SDValue TPReg = DAG.getRegister(CSKY::R31, MVT::i32);1332return DAG.getNode(ISD::ADD, DL, Ty, Load, TPReg);1333}13341335SDValue CSKYTargetLowering::getDynamicTLSAddr(GlobalAddressSDNode *N,1336SelectionDAG &DAG) const {1337MachineFunction &MF = DAG.getMachineFunction();1338CSKYMachineFunctionInfo *CFI = MF.getInfo<CSKYMachineFunctionInfo>();13391340unsigned CSKYPCLabelIndex = CFI->createPICLabelUId();13411342SDLoc DL(N);1343EVT Ty = getPointerTy(DAG.getDataLayout());1344IntegerType *CallTy = Type::getIntNTy(*DAG.getContext(), Ty.getSizeInBits());13451346CSKYConstantPoolValue *CPV =1347CSKYConstantPoolConstant::Create(N->getGlobal(), CSKYCP::CPValue, 4,1348CSKYCP::TLSGD, true, CSKYPCLabelIndex);1349SDValue Addr = DAG.getTargetConstantPool(CPV, Ty);1350SDValue PICLabel = DAG.getTargetConstant(CSKYPCLabelIndex, DL, MVT::i32);13511352auto *LRWGRS =1353DAG.getMachineNode(CSKY::PseudoTLSLA32, DL, {Ty, Ty}, {Addr, PICLabel});13541355auto Load =1356DAG.getNode(ISD::ADD, DL, Ty, SDValue(LRWGRS, 0), SDValue(LRWGRS, 1));13571358// Prepare argument list to generate call.1359ArgListTy Args;1360ArgListEntry Entry;1361Entry.Node = Load;1362Entry.Ty = CallTy;1363Args.push_back(Entry);13641365// Setup call to __tls_get_addr.1366TargetLowering::CallLoweringInfo CLI(DAG);1367CLI.setDebugLoc(DL)1368.setChain(DAG.getEntryNode())1369.setLibCallee(CallingConv::C, CallTy,1370DAG.getExternalSymbol("__tls_get_addr", Ty),1371std::move(Args));1372SDValue V = LowerCallTo(CLI).first;13731374return V;1375}13761377bool CSKYTargetLowering::decomposeMulByConstant(LLVMContext &Context, EVT VT,1378SDValue C) const {1379if (!VT.isScalarInteger())1380return false;13811382// Omit if data size exceeds.1383if (VT.getSizeInBits() > Subtarget.XLen)1384return false;13851386if (auto *ConstNode = dyn_cast<ConstantSDNode>(C.getNode())) {1387const APInt &Imm = ConstNode->getAPIntValue();1388// Break MULT to LSLI + ADDU/SUBU.1389if ((Imm + 1).isPowerOf2() || (Imm - 1).isPowerOf2() ||1390(1 - Imm).isPowerOf2())1391return true;1392// Only break MULT for sub targets without MULT32, since an extra1393// instruction will be generated against the above 3 cases. We leave it1394// unchanged on sub targets with MULT32, since not sure it is better.1395if (!Subtarget.hasE2() && (-1 - Imm).isPowerOf2())1396return true;1397// Break (MULT x, imm) to ([IXH32|IXW32|IXD32] (LSLI32 x, i0), x) when1398// imm=(1<<i0)+[2|4|8] and imm has to be composed via a MOVIH32/ORI32 pair.1399if (Imm.ugt(0xffff) && ((Imm - 2).isPowerOf2() || (Imm - 4).isPowerOf2()) &&1400Subtarget.hasE2())1401return true;1402if (Imm.ugt(0xffff) && (Imm - 8).isPowerOf2() && Subtarget.has2E3())1403return true;1404}14051406return false;1407}14081409bool CSKYTargetLowering::isCheapToSpeculateCttz(Type *Ty) const {1410return Subtarget.has2E3();1411}14121413bool CSKYTargetLowering::isCheapToSpeculateCtlz(Type *Ty) const {1414return Subtarget.hasE2();1415}141614171418