//===-- CSKYISelLowering.cpp - CSKY DAG Lowering Implementation  ----------===//
//
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
// See https://llvm.org/LICENSE.txt for license information.
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
//
//===----------------------------------------------------------------------===//
//
// This file defines the interfaces that CSKY uses to lower LLVM code into a
// selection DAG.
//
//===----------------------------------------------------------------------===//

#include "CSKYISelLowering.h"
#include "CSKYCallingConv.h"
#include "CSKYConstantPoolValue.h"
#include "CSKYMachineFunctionInfo.h"
#include "CSKYRegisterInfo.h"
#include "CSKYSubtarget.h"
#include "llvm/ADT/Statistic.h"
#include "llvm/CodeGen/CallingConvLower.h"
#include "llvm/CodeGen/MachineFrameInfo.h"
#include "llvm/CodeGen/MachineJumpTableInfo.h"
#include "llvm/Support/Debug.h"

using namespace llvm;

#define DEBUG_TYPE "csky-isel-lowering"

STATISTIC(NumTailCalls, "Number of tail calls");

#include "CSKYGenCallingConv.inc"

static const MCPhysReg GPRArgRegs[] = {CSKY::R0, CSKY::R1, CSKY::R2, CSKY::R3};

CSKYTargetLowering::CSKYTargetLowering(const TargetMachine &TM,
                                       const CSKYSubtarget &STI)
    : TargetLowering(TM), Subtarget(STI) {
  // Register Class
  addRegisterClass(MVT::i32, &CSKY::GPRRegClass);

  if (STI.useHardFloat()) {
    if (STI.hasFPUv2SingleFloat())
      addRegisterClass(MVT::f32, &CSKY::sFPR32RegClass);
    else if (STI.hasFPUv3SingleFloat())
      addRegisterClass(MVT::f32, &CSKY::FPR32RegClass);

    if (STI.hasFPUv2DoubleFloat())
      addRegisterClass(MVT::f64, &CSKY::sFPR64RegClass);
    else if (STI.hasFPUv3DoubleFloat())
      addRegisterClass(MVT::f64, &CSKY::FPR64RegClass);
  }

  setOperationAction(ISD::UADDO_CARRY, MVT::i32, Legal);
  setOperationAction(ISD::USUBO_CARRY, MVT::i32, Legal);
  setOperationAction(ISD::BITREVERSE, MVT::i32, Legal);

  setOperationAction(ISD::SREM, MVT::i32, Expand);
  setOperationAction(ISD::UREM, MVT::i32, Expand);
  setOperationAction(ISD::UDIVREM, MVT::i32, Expand);
  setOperationAction(ISD::SDIVREM, MVT::i32, Expand);
  setOperationAction(ISD::CTPOP, MVT::i32, Expand);
  setOperationAction(ISD::ROTR, MVT::i32, Expand);
  setOperationAction(ISD::SHL_PARTS, MVT::i32, Expand);
  setOperationAction(ISD::SRL_PARTS, MVT::i32, Expand);
  setOperationAction(ISD::SRA_PARTS, MVT::i32, Expand);
  setOperationAction(ISD::UMUL_LOHI, MVT::i32, Expand);
  setOperationAction(ISD::SMUL_LOHI, MVT::i32, Expand);
  setOperationAction(ISD::SELECT_CC, MVT::i32, Expand);
  setOperationAction(ISD::BR_CC, MVT::i32, Expand);
  setOperationAction(ISD::BR_JT, MVT::Other, Expand);
  setOperationAction(ISD::DYNAMIC_STACKALLOC, MVT::i32, Expand);
  setOperationAction(ISD::STACKSAVE, MVT::Other, Expand);
  setOperationAction(ISD::STACKRESTORE, MVT::Other, Expand);
  setOperationAction(ISD::MULHS, MVT::i32, Expand);
  setOperationAction(ISD::MULHU, MVT::i32, Expand);
  setOperationAction(ISD::VAARG, MVT::Other, Expand);
  setOperationAction(ISD::VACOPY, MVT::Other, Expand);
  setOperationAction(ISD::VAEND, MVT::Other, Expand);

  setLoadExtAction(ISD::EXTLOAD, MVT::i32, MVT::i1, Promote);
  setLoadExtAction(ISD::SEXTLOAD, MVT::i32, MVT::i1, Promote);
  setLoadExtAction(ISD::ZEXTLOAD, MVT::i32, MVT::i1, Promote);

  setOperationAction(ISD::GlobalAddress, MVT::i32, Custom);
  setOperationAction(ISD::ExternalSymbol, MVT::i32, Custom);
  setOperationAction(ISD::GlobalTLSAddress, MVT::i32, Custom);
  setOperationAction(ISD::BlockAddress, MVT::i32, Custom);
  if (!Subtarget.hasE2()) {
    setOperationAction(ISD::ConstantPool, MVT::i32, Custom);
  }
  setOperationAction(ISD::JumpTable, MVT::i32, Custom);
  setOperationAction(ISD::VASTART, MVT::Other, Custom);

  if (!Subtarget.hasE2()) {
    setLoadExtAction(ISD::SEXTLOAD, MVT::i32, MVT::i8, Expand);
    setLoadExtAction(ISD::SEXTLOAD, MVT::i32, MVT::i16, Expand);
    setOperationAction(ISD::CTLZ, MVT::i32, Expand);
    setOperationAction(ISD::BSWAP, MVT::i32, Expand);
  }

  if (!Subtarget.has2E3()) {
    setOperationAction(ISD::ABS, MVT::i32, Expand);
    setOperationAction(ISD::BITREVERSE, MVT::i32, Expand);
    setOperationAction(ISD::CTTZ, MVT::i32, Expand);
    setOperationAction(ISD::SDIV, MVT::i32, Expand);
    setOperationAction(ISD::UDIV, MVT::i32, Expand);
  }

  setOperationAction(ISD::ATOMIC_FENCE, MVT::Other, Expand);

  // Float

  ISD::CondCode FPCCToExtend[] = {
      ISD::SETONE, ISD::SETUEQ, ISD::SETUGT,
      ISD::SETUGE, ISD::SETULT, ISD::SETULE,
  };

  ISD::NodeType FPOpToExpand[] = {
      ISD::FSIN, ISD::FCOS,      ISD::FSINCOS,    ISD::FPOW,
      ISD::FREM, ISD::FCOPYSIGN, ISD::FP16_TO_FP, ISD::FP_TO_FP16};

  if (STI.useHardFloat()) {

    MVT AllVTy[] = {MVT::f32, MVT::f64};

    for (auto VT : AllVTy) {
      setOperationAction(ISD::FREM, VT, Expand);
      setOperationAction(ISD::SELECT_CC, VT, Expand);
      setOperationAction(ISD::BR_CC, VT, Expand);

      for (auto CC : FPCCToExtend)
        setCondCodeAction(CC, VT, Expand);
      for (auto Op : FPOpToExpand)
        setOperationAction(Op, VT, Expand);
    }

    if (STI.hasFPUv2SingleFloat() || STI.hasFPUv3SingleFloat()) {
      setOperationAction(ISD::ConstantFP, MVT::f32, Legal);
      setLoadExtAction(ISD::EXTLOAD, MVT::f32, MVT::f16, Expand);
      setTruncStoreAction(MVT::f32, MVT::f16, Expand);
    }
    if (STI.hasFPUv2DoubleFloat() || STI.hasFPUv3DoubleFloat()) {
      setLoadExtAction(ISD::EXTLOAD, MVT::f64, MVT::f32, Expand);
      setTruncStoreAction(MVT::f64, MVT::f32, Expand);
      setLoadExtAction(ISD::EXTLOAD, MVT::f64, MVT::f16, Expand);
      setTruncStoreAction(MVT::f64, MVT::f16, Expand);
    }
  }

  // Compute derived properties from the register classes.
  computeRegisterProperties(STI.getRegisterInfo());

  setBooleanContents(UndefinedBooleanContent);
  setBooleanVectorContents(ZeroOrNegativeOneBooleanContent);

  // TODO: Add atomic support fully.
  setMaxAtomicSizeInBitsSupported(0);

  setStackPointerRegisterToSaveRestore(CSKY::R14);
  setMinFunctionAlignment(Align(2));
  setSchedulingPreference(Sched::Source);
}

SDValue CSKYTargetLowering::LowerOperation(SDValue Op,
                                           SelectionDAG &DAG) const {
  switch (Op.getOpcode()) {
  default:
    llvm_unreachable("unimplemented op");
  case ISD::GlobalAddress:
    return LowerGlobalAddress(Op, DAG);
  case ISD::ExternalSymbol:
    return LowerExternalSymbol(Op, DAG);
  case ISD::GlobalTLSAddress:
    return LowerGlobalTLSAddress(Op, DAG);
  case ISD::JumpTable:
    return LowerJumpTable(Op, DAG);
  case ISD::BlockAddress:
    return LowerBlockAddress(Op, DAG);
  case ISD::ConstantPool:
    return LowerConstantPool(Op, DAG);
  case ISD::VASTART:
    return LowerVASTART(Op, DAG);
  case ISD::FRAMEADDR:
    return LowerFRAMEADDR(Op, DAG);
  case ISD::RETURNADDR:
    return LowerRETURNADDR(Op, DAG);
  }
}

EVT CSKYTargetLowering::getSetCCResultType(const DataLayout &DL,
                                           LLVMContext &Context, EVT VT) const {
  if (!VT.isVector())
    return MVT::i32;

  return VT.changeVectorElementTypeToInteger();
}

static SDValue convertValVTToLocVT(SelectionDAG &DAG, SDValue Val,
                                   const CCValAssign &VA, const SDLoc &DL) {
  EVT LocVT = VA.getLocVT();

  switch (VA.getLocInfo()) {
  default:
    llvm_unreachable("Unexpected CCValAssign::LocInfo");
  case CCValAssign::Full:
    break;
  case CCValAssign::BCvt:
    Val = DAG.getNode(ISD::BITCAST, DL, LocVT, Val);
    break;
  }
  return Val;
}

static SDValue convertLocVTToValVT(SelectionDAG &DAG, SDValue Val,
                                   const CCValAssign &VA, const SDLoc &DL) {
  switch (VA.getLocInfo()) {
  default:
    llvm_unreachable("Unexpected CCValAssign::LocInfo");
  case CCValAssign::Full:
    break;
  case CCValAssign::BCvt:
    Val = DAG.getNode(ISD::BITCAST, DL, VA.getValVT(), Val);
    break;
  }
  return Val;
}

static SDValue unpackFromRegLoc(const CSKYSubtarget &Subtarget,
                                SelectionDAG &DAG, SDValue Chain,
                                const CCValAssign &VA, const SDLoc &DL) {
  MachineFunction &MF = DAG.getMachineFunction();
  MachineRegisterInfo &RegInfo = MF.getRegInfo();
  EVT LocVT = VA.getLocVT();
  SDValue Val;
  const TargetRegisterClass *RC;

  switch (LocVT.getSimpleVT().SimpleTy) {
  default:
    llvm_unreachable("Unexpected register type");
  case MVT::i32:
    RC = &CSKY::GPRRegClass;
    break;
  case MVT::f32:
    RC = Subtarget.hasFPUv2SingleFloat() ? &CSKY::sFPR32RegClass
                                         : &CSKY::FPR32RegClass;
    break;
  case MVT::f64:
    RC = Subtarget.hasFPUv2DoubleFloat() ? &CSKY::sFPR64RegClass
                                         : &CSKY::FPR64RegClass;
    break;
  }

  Register VReg = RegInfo.createVirtualRegister(RC);
  RegInfo.addLiveIn(VA.getLocReg(), VReg);
  Val = DAG.getCopyFromReg(Chain, DL, VReg, LocVT);

  return convertLocVTToValVT(DAG, Val, VA, DL);
}

static SDValue unpackFromMemLoc(SelectionDAG &DAG, SDValue Chain,
                                const CCValAssign &VA, const SDLoc &DL) {
  MachineFunction &MF = DAG.getMachineFunction();
  MachineFrameInfo &MFI = MF.getFrameInfo();
  EVT LocVT = VA.getLocVT();
  EVT ValVT = VA.getValVT();
  EVT PtrVT = MVT::getIntegerVT(DAG.getDataLayout().getPointerSizeInBits(0));
  int FI = MFI.CreateFixedObject(ValVT.getSizeInBits() / 8,
                                 VA.getLocMemOffset(), /*Immutable=*/true);
  SDValue FIN = DAG.getFrameIndex(FI, PtrVT);
  SDValue Val;

  ISD::LoadExtType ExtType;
  switch (VA.getLocInfo()) {
  default:
    llvm_unreachable("Unexpected CCValAssign::LocInfo");
  case CCValAssign::Full:
  case CCValAssign::BCvt:
    ExtType = ISD::NON_EXTLOAD;
    break;
  }
  Val = DAG.getExtLoad(
      ExtType, DL, LocVT, Chain, FIN,
      MachinePointerInfo::getFixedStack(DAG.getMachineFunction(), FI), ValVT);
  return Val;
}

static SDValue unpack64(SelectionDAG &DAG, SDValue Chain, const CCValAssign &VA,
                        const SDLoc &DL) {
  assert(VA.getLocVT() == MVT::i32 &&
         (VA.getValVT() == MVT::f64 || VA.getValVT() == MVT::i64) &&
         "Unexpected VA");
  MachineFunction &MF = DAG.getMachineFunction();
  MachineFrameInfo &MFI = MF.getFrameInfo();
  MachineRegisterInfo &RegInfo = MF.getRegInfo();

  if (VA.isMemLoc()) {
    // f64/i64 is passed on the stack.
    int FI = MFI.CreateFixedObject(8, VA.getLocMemOffset(), /*Immutable=*/true);
    SDValue FIN = DAG.getFrameIndex(FI, MVT::i32);
    return DAG.getLoad(VA.getValVT(), DL, Chain, FIN,
                       MachinePointerInfo::getFixedStack(MF, FI));
  }

  assert(VA.isRegLoc() && "Expected register VA assignment");

  Register LoVReg = RegInfo.createVirtualRegister(&CSKY::GPRRegClass);
  RegInfo.addLiveIn(VA.getLocReg(), LoVReg);
  SDValue Lo = DAG.getCopyFromReg(Chain, DL, LoVReg, MVT::i32);
  SDValue Hi;
  if (VA.getLocReg() == CSKY::R3) {
    // Second half of f64/i64 is passed on the stack.
    int FI = MFI.CreateFixedObject(4, 0, /*Immutable=*/true);
    SDValue FIN = DAG.getFrameIndex(FI, MVT::i32);
    Hi = DAG.getLoad(MVT::i32, DL, Chain, FIN,
                     MachinePointerInfo::getFixedStack(MF, FI));
  } else {
    // Second half of f64/i64 is passed in another GPR.
    Register HiVReg = RegInfo.createVirtualRegister(&CSKY::GPRRegClass);
    RegInfo.addLiveIn(VA.getLocReg() + 1, HiVReg);
    Hi = DAG.getCopyFromReg(Chain, DL, HiVReg, MVT::i32);
  }
  return DAG.getNode(CSKYISD::BITCAST_FROM_LOHI, DL, VA.getValVT(), Lo, Hi);
}

// Transform physical registers into virtual registers.
SDValue CSKYTargetLowering::LowerFormalArguments(
    SDValue Chain, CallingConv::ID CallConv, bool IsVarArg,
    const SmallVectorImpl<ISD::InputArg> &Ins, const SDLoc &DL,
    SelectionDAG &DAG, SmallVectorImpl<SDValue> &InVals) const {

  switch (CallConv) {
  default:
    report_fatal_error("Unsupported calling convention");
  case CallingConv::C:
  case CallingConv::Fast:
    break;
  }

  MachineFunction &MF = DAG.getMachineFunction();

  // Used with vargs to acumulate store chains.
  std::vector<SDValue> OutChains;

  // Assign locations to all of the incoming arguments.
  SmallVector<CCValAssign, 16> ArgLocs;
  CCState CCInfo(CallConv, IsVarArg, MF, ArgLocs, *DAG.getContext());

  CCInfo.AnalyzeFormalArguments(Ins, CCAssignFnForCall(CallConv, IsVarArg));

  for (unsigned i = 0, e = ArgLocs.size(); i != e; ++i) {
    CCValAssign &VA = ArgLocs[i];
    SDValue ArgValue;

    bool IsF64OnCSKY = VA.getLocVT() == MVT::i32 && VA.getValVT() == MVT::f64;

    if (IsF64OnCSKY)
      ArgValue = unpack64(DAG, Chain, VA, DL);
    else if (VA.isRegLoc())
      ArgValue = unpackFromRegLoc(Subtarget, DAG, Chain, VA, DL);
    else
      ArgValue = unpackFromMemLoc(DAG, Chain, VA, DL);

    InVals.push_back(ArgValue);
  }

  if (IsVarArg) {
    const unsigned XLenInBytes = 4;
    const MVT XLenVT = MVT::i32;

    ArrayRef<MCPhysReg> ArgRegs = ArrayRef(GPRArgRegs);
    unsigned Idx = CCInfo.getFirstUnallocated(ArgRegs);
    const TargetRegisterClass *RC = &CSKY::GPRRegClass;
    MachineFrameInfo &MFI = MF.getFrameInfo();
    MachineRegisterInfo &RegInfo = MF.getRegInfo();
    CSKYMachineFunctionInfo *CSKYFI = MF.getInfo<CSKYMachineFunctionInfo>();

    // Offset of the first variable argument from stack pointer, and size of
    // the vararg save area. For now, the varargs save area is either zero or
    // large enough to hold a0-a4.
    int VaArgOffset, VarArgsSaveSize;

    // If all registers are allocated, then all varargs must be passed on the
    // stack and we don't need to save any argregs.
    if (ArgRegs.size() == Idx) {
      VaArgOffset = CCInfo.getStackSize();
      VarArgsSaveSize = 0;
    } else {
      VarArgsSaveSize = XLenInBytes * (ArgRegs.size() - Idx);
      VaArgOffset = -VarArgsSaveSize;
    }

    // Record the frame index of the first variable argument
    // which is a value necessary to VASTART.
    int FI = MFI.CreateFixedObject(XLenInBytes, VaArgOffset, true);
    CSKYFI->setVarArgsFrameIndex(FI);

    // Copy the integer registers that may have been used for passing varargs
    // to the vararg save area.
    for (unsigned I = Idx; I < ArgRegs.size();
         ++I, VaArgOffset += XLenInBytes) {
      const Register Reg = RegInfo.createVirtualRegister(RC);
      RegInfo.addLiveIn(ArgRegs[I], Reg);
      SDValue ArgValue = DAG.getCopyFromReg(Chain, DL, Reg, XLenVT);
      FI = MFI.CreateFixedObject(XLenInBytes, VaArgOffset, true);
      SDValue PtrOff = DAG.getFrameIndex(FI, getPointerTy(DAG.getDataLayout()));
      SDValue Store = DAG.getStore(Chain, DL, ArgValue, PtrOff,
                                   MachinePointerInfo::getFixedStack(MF, FI));
      cast<StoreSDNode>(Store.getNode())
          ->getMemOperand()
          ->setValue((Value *)nullptr);
      OutChains.push_back(Store);
    }
    CSKYFI->setVarArgsSaveSize(VarArgsSaveSize);
  }

  // All stores are grouped in one node to allow the matching between
  // the size of Ins and InVals. This only happens for vararg functions.
  if (!OutChains.empty()) {
    OutChains.push_back(Chain);
    Chain = DAG.getNode(ISD::TokenFactor, DL, MVT::Other, OutChains);
  }

  return Chain;
}

bool CSKYTargetLowering::CanLowerReturn(
    CallingConv::ID CallConv, MachineFunction &MF, bool IsVarArg,
    const SmallVectorImpl<ISD::OutputArg> &Outs, LLVMContext &Context,
    const Type *RetTy) const {
  SmallVector<CCValAssign, 16> CSKYLocs;
  CCState CCInfo(CallConv, IsVarArg, MF, CSKYLocs, Context);
  return CCInfo.CheckReturn(Outs, CCAssignFnForReturn(CallConv, IsVarArg));
}

SDValue
CSKYTargetLowering::LowerReturn(SDValue Chain, CallingConv::ID CallConv,
                                bool IsVarArg,
                                const SmallVectorImpl<ISD::OutputArg> &Outs,
                                const SmallVectorImpl<SDValue> &OutVals,
                                const SDLoc &DL, SelectionDAG &DAG) const {
  // Stores the assignment of the return value to a location.
  SmallVector<CCValAssign, 16> CSKYLocs;

  // Info about the registers and stack slot.
  CCState CCInfo(CallConv, IsVarArg, DAG.getMachineFunction(), CSKYLocs,
                 *DAG.getContext());
  CCInfo.AnalyzeReturn(Outs, CCAssignFnForReturn(CallConv, IsVarArg));

  SDValue Glue;
  SmallVector<SDValue, 4> RetOps(1, Chain);

  // Copy the result values into the output registers.
  for (unsigned i = 0, e = CSKYLocs.size(); i < e; ++i) {
    SDValue Val = OutVals[i];
    CCValAssign &VA = CSKYLocs[i];
    assert(VA.isRegLoc() && "Can only return in registers!");

    bool IsF64OnCSKY = VA.getLocVT() == MVT::i32 && VA.getValVT() == MVT::f64;

    if (IsF64OnCSKY) {

      assert(VA.isRegLoc() && "Expected return via registers");
      SDValue Split64 = DAG.getNode(CSKYISD::BITCAST_TO_LOHI, DL,
                                    DAG.getVTList(MVT::i32, MVT::i32), Val);
      SDValue Lo = Split64.getValue(0);
      SDValue Hi = Split64.getValue(1);

      Register RegLo = VA.getLocReg();
      assert(RegLo < CSKY::R31 && "Invalid register pair");
      Register RegHi = RegLo + 1;

      Chain = DAG.getCopyToReg(Chain, DL, RegLo, Lo, Glue);
      Glue = Chain.getValue(1);
      RetOps.push_back(DAG.getRegister(RegLo, MVT::i32));
      Chain = DAG.getCopyToReg(Chain, DL, RegHi, Hi, Glue);
      Glue = Chain.getValue(1);
      RetOps.push_back(DAG.getRegister(RegHi, MVT::i32));
    } else {
      // Handle a 'normal' return.
      Val = convertValVTToLocVT(DAG, Val, VA, DL);
      Chain = DAG.getCopyToReg(Chain, DL, VA.getLocReg(), Val, Glue);

      // Guarantee that all emitted copies are stuck together.
      Glue = Chain.getValue(1);
      RetOps.push_back(DAG.getRegister(VA.getLocReg(), VA.getLocVT()));
    }
  }

  RetOps[0] = Chain; // Update chain.

  // Add the glue node if we have it.
  if (Glue.getNode()) {
    RetOps.push_back(Glue);
  }

  // Interrupt service routines use different return instructions.
  if (DAG.getMachineFunction().getFunction().hasFnAttribute("interrupt"))
    return DAG.getNode(CSKYISD::NIR, DL, MVT::Other, RetOps);

  return DAG.getNode(CSKYISD::RET, DL, MVT::Other, RetOps);
}

// Lower a call to a callseq_start + CALL + callseq_end chain, and add input
// and output parameter nodes.
SDValue CSKYTargetLowering::LowerCall(CallLoweringInfo &CLI,
                                      SmallVectorImpl<SDValue> &InVals) const {
  SelectionDAG &DAG = CLI.DAG;
  SDLoc &DL = CLI.DL;
  SmallVectorImpl<ISD::OutputArg> &Outs = CLI.Outs;
  SmallVectorImpl<SDValue> &OutVals = CLI.OutVals;
  SmallVectorImpl<ISD::InputArg> &Ins = CLI.Ins;
  SDValue Chain = CLI.Chain;
  SDValue Callee = CLI.Callee;
  bool &IsTailCall = CLI.IsTailCall;
  CallingConv::ID CallConv = CLI.CallConv;
  bool IsVarArg = CLI.IsVarArg;
  EVT PtrVT = getPointerTy(DAG.getDataLayout());
  MVT XLenVT = MVT::i32;

  MachineFunction &MF = DAG.getMachineFunction();

  // Analyze the operands of the call, assigning locations to each operand.
  SmallVector<CCValAssign, 16> ArgLocs;
  CCState ArgCCInfo(CallConv, IsVarArg, MF, ArgLocs, *DAG.getContext());

  ArgCCInfo.AnalyzeCallOperands(Outs, CCAssignFnForCall(CallConv, IsVarArg));

  // Check if it's really possible to do a tail call.
  if (IsTailCall)
    IsTailCall = false; // TODO: TailCallOptimization;

  if (IsTailCall)
    ++NumTailCalls;
  else if (CLI.CB && CLI.CB->isMustTailCall())
    report_fatal_error("failed to perform tail call elimination on a call "
                       "site marked musttail");

  // Get a count of how many bytes are to be pushed on the stack.
  unsigned NumBytes = ArgCCInfo.getStackSize();

  // Create local copies for byval args
  SmallVector<SDValue, 8> ByValArgs;
  for (unsigned i = 0, e = Outs.size(); i != e; ++i) {
    ISD::ArgFlagsTy Flags = Outs[i].Flags;
    if (!Flags.isByVal())
      continue;

    SDValue Arg = OutVals[i];
    unsigned Size = Flags.getByValSize();
    Align Alignment = Flags.getNonZeroByValAlign();

    int FI =
        MF.getFrameInfo().CreateStackObject(Size, Alignment, /*isSS=*/false);
    SDValue FIPtr = DAG.getFrameIndex(FI, getPointerTy(DAG.getDataLayout()));
    SDValue SizeNode = DAG.getConstant(Size, DL, XLenVT);

    Chain = DAG.getMemcpy(Chain, DL, FIPtr, Arg, SizeNode, Alignment,
                          /*IsVolatile=*/false,
                          /*AlwaysInline=*/false, /*CI=*/nullptr, IsTailCall,
                          MachinePointerInfo(), MachinePointerInfo());
    ByValArgs.push_back(FIPtr);
  }

  if (!IsTailCall)
    Chain = DAG.getCALLSEQ_START(Chain, NumBytes, 0, CLI.DL);

  // Copy argument values to their designated locations.
  SmallVector<std::pair<Register, SDValue>, 8> RegsToPass;
  SmallVector<SDValue, 8> MemOpChains;
  SDValue StackPtr;
  for (unsigned i = 0, j = 0, e = ArgLocs.size(); i != e; ++i) {
    CCValAssign &VA = ArgLocs[i];
    SDValue ArgValue = OutVals[i];
    ISD::ArgFlagsTy Flags = Outs[i].Flags;

    bool IsF64OnCSKY = VA.getLocVT() == MVT::i32 && VA.getValVT() == MVT::f64;

    if (IsF64OnCSKY && VA.isRegLoc()) {
      SDValue Split64 =
          DAG.getNode(CSKYISD::BITCAST_TO_LOHI, DL,
                      DAG.getVTList(MVT::i32, MVT::i32), ArgValue);
      SDValue Lo = Split64.getValue(0);
      SDValue Hi = Split64.getValue(1);

      Register RegLo = VA.getLocReg();
      RegsToPass.push_back(std::make_pair(RegLo, Lo));

      if (RegLo == CSKY::R3) {
        // Second half of f64/i64 is passed on the stack.
        // Work out the address of the stack slot.
        if (!StackPtr.getNode())
          StackPtr = DAG.getCopyFromReg(Chain, DL, CSKY::R14, PtrVT);
        // Emit the store.
        MemOpChains.push_back(
            DAG.getStore(Chain, DL, Hi, StackPtr, MachinePointerInfo()));
      } else {
        // Second half of f64/i64 is passed in another GPR.
        assert(RegLo < CSKY::R31 && "Invalid register pair");
        Register RegHigh = RegLo + 1;
        RegsToPass.push_back(std::make_pair(RegHigh, Hi));
      }
      continue;
    }

    ArgValue = convertValVTToLocVT(DAG, ArgValue, VA, DL);

    // Use local copy if it is a byval arg.
    if (Flags.isByVal())
      ArgValue = ByValArgs[j++];

    if (VA.isRegLoc()) {
      // Queue up the argument copies and emit them at the end.
      RegsToPass.push_back(std::make_pair(VA.getLocReg(), ArgValue));
    } else {
      assert(VA.isMemLoc() && "Argument not register or memory");
      assert(!IsTailCall && "Tail call not allowed if stack is used "
                            "for passing parameters");

      // Work out the address of the stack slot.
      if (!StackPtr.getNode())
        StackPtr = DAG.getCopyFromReg(Chain, DL, CSKY::R14, PtrVT);
      SDValue Address =
          DAG.getNode(ISD::ADD, DL, PtrVT, StackPtr,
                      DAG.getIntPtrConstant(VA.getLocMemOffset(), DL));

      // Emit the store.
      MemOpChains.push_back(
          DAG.getStore(Chain, DL, ArgValue, Address, MachinePointerInfo()));
    }
  }

  // Join the stores, which are independent of one another.
  if (!MemOpChains.empty())
    Chain = DAG.getNode(ISD::TokenFactor, DL, MVT::Other, MemOpChains);

  SDValue Glue;

  // Build a sequence of copy-to-reg nodes, chained and glued together.
  for (auto &Reg : RegsToPass) {
    Chain = DAG.getCopyToReg(Chain, DL, Reg.first, Reg.second, Glue);
    Glue = Chain.getValue(1);
  }

  SmallVector<SDValue, 8> Ops;
  EVT Ty = getPointerTy(DAG.getDataLayout());
  bool IsRegCall = false;

  Ops.push_back(Chain);

  if (GlobalAddressSDNode *S = dyn_cast<GlobalAddressSDNode>(Callee)) {
    const GlobalValue *GV = S->getGlobal();
    bool IsLocal = getTargetMachine().shouldAssumeDSOLocal(GV);

    if (isPositionIndependent() || !Subtarget.has2E3()) {
      IsRegCall = true;
      Ops.push_back(getAddr<GlobalAddressSDNode, true>(S, DAG, IsLocal));
    } else {
      Ops.push_back(getTargetNode(cast<GlobalAddressSDNode>(Callee), DL, Ty,
                                  DAG, CSKYII::MO_None));
      Ops.push_back(getTargetConstantPoolValue(
          cast<GlobalAddressSDNode>(Callee), Ty, DAG, CSKYII::MO_None));
    }
  } else if (ExternalSymbolSDNode *S = dyn_cast<ExternalSymbolSDNode>(Callee)) {
    bool IsLocal = getTargetMachine().shouldAssumeDSOLocal(nullptr);

    if (isPositionIndependent() || !Subtarget.has2E3()) {
      IsRegCall = true;
      Ops.push_back(getAddr<ExternalSymbolSDNode, true>(S, DAG, IsLocal));
    } else {
      Ops.push_back(getTargetNode(cast<ExternalSymbolSDNode>(Callee), DL, Ty,
                                  DAG, CSKYII::MO_None));
      Ops.push_back(getTargetConstantPoolValue(
          cast<ExternalSymbolSDNode>(Callee), Ty, DAG, CSKYII::MO_None));
    }
  } else {
    IsRegCall = true;
    Ops.push_back(Callee);
  }

  // Add argument registers to the end of the list so that they are
  // known live into the call.
  for (auto &Reg : RegsToPass)
    Ops.push_back(DAG.getRegister(Reg.first, Reg.second.getValueType()));

  if (!IsTailCall) {
    // Add a register mask operand representing the call-preserved registers.
    const TargetRegisterInfo *TRI = Subtarget.getRegisterInfo();
    const uint32_t *Mask = TRI->getCallPreservedMask(MF, CallConv);
    assert(Mask && "Missing call preserved mask for calling convention");
    Ops.push_back(DAG.getRegisterMask(Mask));
  }

  // Glue the call to the argument copies, if any.
  if (Glue.getNode())
    Ops.push_back(Glue);

  // Emit the call.
  SDVTList NodeTys = DAG.getVTList(MVT::Other, MVT::Glue);

  if (IsTailCall) {
    MF.getFrameInfo().setHasTailCall();
    return DAG.getNode(IsRegCall ? CSKYISD::TAILReg : CSKYISD::TAIL, DL,
                       NodeTys, Ops);
  }

  Chain = DAG.getNode(IsRegCall ? CSKYISD::CALLReg : CSKYISD::CALL, DL, NodeTys,
                      Ops);
  DAG.addNoMergeSiteInfo(Chain.getNode(), CLI.NoMerge);
  Glue = Chain.getValue(1);

  // Mark the end of the call, which is glued to the call itself.
  Chain = DAG.getCALLSEQ_END(Chain, NumBytes, 0, Glue, DL);
  Glue = Chain.getValue(1);

  // Assign locations to each value returned by this call.
  SmallVector<CCValAssign, 16> CSKYLocs;
  CCState RetCCInfo(CallConv, IsVarArg, MF, CSKYLocs, *DAG.getContext());
  RetCCInfo.AnalyzeCallResult(Ins, CCAssignFnForReturn(CallConv, IsVarArg));

  // Copy all of the result registers out of their specified physreg.
  for (auto &VA : CSKYLocs) {
    // Copy the value out
    SDValue RetValue =
        DAG.getCopyFromReg(Chain, DL, VA.getLocReg(), VA.getLocVT(), Glue);
    // Glue the RetValue to the end of the call sequence
    Chain = RetValue.getValue(1);
    Glue = RetValue.getValue(2);

    bool IsF64OnCSKY = VA.getLocVT() == MVT::i32 && VA.getValVT() == MVT::f64;

    if (IsF64OnCSKY) {
      assert(VA.getLocReg() == GPRArgRegs[0] && "Unexpected reg assignment");
      SDValue RetValue2 =
          DAG.getCopyFromReg(Chain, DL, GPRArgRegs[1], MVT::i32, Glue);
      Chain = RetValue2.getValue(1);
      Glue = RetValue2.getValue(2);
      RetValue = DAG.getNode(CSKYISD::BITCAST_FROM_LOHI, DL, VA.getValVT(),
                             RetValue, RetValue2);
    }

    RetValue = convertLocVTToValVT(DAG, RetValue, VA, DL);

    InVals.push_back(RetValue);
  }

  return Chain;
}

CCAssignFn *CSKYTargetLowering::CCAssignFnForReturn(CallingConv::ID CC,
                                                    bool IsVarArg) const {
  if (IsVarArg || !Subtarget.useHardFloatABI())
    return RetCC_CSKY_ABIV2_SOFT;
  else
    return RetCC_CSKY_ABIV2_FP;
}

CCAssignFn *CSKYTargetLowering::CCAssignFnForCall(CallingConv::ID CC,
                                                  bool IsVarArg) const {
  if (IsVarArg || !Subtarget.useHardFloatABI())
    return CC_CSKY_ABIV2_SOFT;
  else
    return CC_CSKY_ABIV2_FP;
}

static CSKYCP::CSKYCPModifier getModifier(unsigned Flags) {

  if (Flags == CSKYII::MO_ADDR32)
    return CSKYCP::ADDR;
  else if (Flags == CSKYII::MO_GOT32)
    return CSKYCP::GOT;
  else if (Flags == CSKYII::MO_GOTOFF)
    return CSKYCP::GOTOFF;
  else if (Flags == CSKYII::MO_PLT32)
    return CSKYCP::PLT;
  else if (Flags == CSKYII::MO_None)
    return CSKYCP::NO_MOD;
  else
    assert(0 && "unknown CSKYII Modifier");
  return CSKYCP::NO_MOD;
}

SDValue CSKYTargetLowering::getTargetConstantPoolValue(GlobalAddressSDNode *N,
                                                       EVT Ty,
                                                       SelectionDAG &DAG,
                                                       unsigned Flags) const {
  CSKYConstantPoolValue *CPV = CSKYConstantPoolConstant::Create(
      N->getGlobal(), CSKYCP::CPValue, 0, getModifier(Flags), false);

  return DAG.getTargetConstantPool(CPV, Ty);
}

CSKYTargetLowering::ConstraintType
CSKYTargetLowering::getConstraintType(StringRef Constraint) const {
  if (Constraint.size() == 1) {
    switch (Constraint[0]) {
    default:
      break;
    case 'a':
    case 'b':
    case 'v':
    case 'w':
    case 'y':
      return C_RegisterClass;
    case 'c':
    case 'l':
    case 'h':
    case 'z':
      return C_Register;
    }
  }
  return TargetLowering::getConstraintType(Constraint);
}

std::pair<unsigned, const TargetRegisterClass *>
CSKYTargetLowering::getRegForInlineAsmConstraint(const TargetRegisterInfo *TRI,
                                                 StringRef Constraint,
                                                 MVT VT) const {
  if (Constraint.size() == 1) {
    switch (Constraint[0]) {
    case 'r':
      return std::make_pair(0U, &CSKY::GPRRegClass);
    case 'a':
      return std::make_pair(0U, &CSKY::mGPRRegClass);
    case 'b':
      return std::make_pair(0U, &CSKY::sGPRRegClass);
    case 'z':
      return std::make_pair(CSKY::R14, &CSKY::GPRRegClass);
    case 'c':
      return std::make_pair(CSKY::C, &CSKY::CARRYRegClass);
    case 'w':
      if ((Subtarget.hasFPUv2SingleFloat() ||
           Subtarget.hasFPUv3SingleFloat()) &&
          VT == MVT::f32)
        return std::make_pair(0U, &CSKY::sFPR32RegClass);
      if ((Subtarget.hasFPUv2DoubleFloat() ||
           Subtarget.hasFPUv3DoubleFloat()) &&
          VT == MVT::f64)
        return std::make_pair(0U, &CSKY::sFPR64RegClass);
      break;
    case 'v':
      if (Subtarget.hasFPUv2SingleFloat() && VT == MVT::f32)
        return std::make_pair(0U, &CSKY::sFPR32RegClass);
      if (Subtarget.hasFPUv3SingleFloat() && VT == MVT::f32)
        return std::make_pair(0U, &CSKY::FPR32RegClass);
      if (Subtarget.hasFPUv2DoubleFloat() && VT == MVT::f64)
        return std::make_pair(0U, &CSKY::sFPR64RegClass);
      if (Subtarget.hasFPUv3DoubleFloat() && VT == MVT::f64)
        return std::make_pair(0U, &CSKY::FPR64RegClass);
      break;
    default:
      break;
    }
  }

  if (Constraint == "{c}")
    return std::make_pair(CSKY::C, &CSKY::CARRYRegClass);

  // Clang will correctly decode the usage of register name aliases into their
  // official names. However, other frontends like `rustc` do not. This allows
  // users of these frontends to use the ABI names for registers in LLVM-style
  // register constraints.
  unsigned XRegFromAlias = StringSwitch<unsigned>(Constraint.lower())
                               .Case("{a0}", CSKY::R0)
                               .Case("{a1}", CSKY::R1)
                               .Case("{a2}", CSKY::R2)
                               .Case("{a3}", CSKY::R3)
                               .Case("{l0}", CSKY::R4)
                               .Case("{l1}", CSKY::R5)
                               .Case("{l2}", CSKY::R6)
                               .Case("{l3}", CSKY::R7)
                               .Case("{l4}", CSKY::R8)
                               .Case("{l5}", CSKY::R9)
                               .Case("{l6}", CSKY::R10)
                               .Case("{l7}", CSKY::R11)
                               .Case("{t0}", CSKY::R12)
                               .Case("{t1}", CSKY::R13)
                               .Case("{sp}", CSKY::R14)
                               .Case("{lr}", CSKY::R15)
                               .Case("{l8}", CSKY::R16)
                               .Case("{l9}", CSKY::R17)
                               .Case("{t2}", CSKY::R18)
                               .Case("{t3}", CSKY::R19)
                               .Case("{t4}", CSKY::R20)
                               .Case("{t5}", CSKY::R21)
                               .Case("{t6}", CSKY::R22)
                               .Cases("{t7}", "{fp}", CSKY::R23)
                               .Cases("{t8}", "{top}", CSKY::R24)
                               .Cases("{t9}", "{bsp}", CSKY::R25)
                               .Case("{r26}", CSKY::R26)
                               .Case("{r27}", CSKY::R27)
                               .Cases("{gb}", "{rgb}", "{rdb}", CSKY::R28)
                               .Cases("{tb}", "{rtb}", CSKY::R29)
                               .Case("{svbr}", CSKY::R30)
                               .Case("{tls}", CSKY::R31)
                               .Default(CSKY::NoRegister);

  if (XRegFromAlias != CSKY::NoRegister)
    return std::make_pair(XRegFromAlias, &CSKY::GPRRegClass);

  // Since TargetLowering::getRegForInlineAsmConstraint uses the name of the
  // TableGen record rather than the AsmName to choose registers for InlineAsm
  // constraints, plus we want to match those names to the widest floating point
  // register type available, manually select floating point registers here.
  //
  // The second case is the ABI name of the register, so that frontends can also
  // use the ABI names in register constraint lists.
  if (Subtarget.useHardFloat()) {
    unsigned FReg = StringSwitch<unsigned>(Constraint.lower())
                        .Cases("{fr0}", "{vr0}", CSKY::F0_32)
                        .Cases("{fr1}", "{vr1}", CSKY::F1_32)
                        .Cases("{fr2}", "{vr2}", CSKY::F2_32)
                        .Cases("{fr3}", "{vr3}", CSKY::F3_32)
                        .Cases("{fr4}", "{vr4}", CSKY::F4_32)
                        .Cases("{fr5}", "{vr5}", CSKY::F5_32)
                        .Cases("{fr6}", "{vr6}", CSKY::F6_32)
                        .Cases("{fr7}", "{vr7}", CSKY::F7_32)
                        .Cases("{fr8}", "{vr8}", CSKY::F8_32)
                        .Cases("{fr9}", "{vr9}", CSKY::F9_32)
                        .Cases("{fr10}", "{vr10}", CSKY::F10_32)
                        .Cases("{fr11}", "{vr11}", CSKY::F11_32)
                        .Cases("{fr12}", "{vr12}", CSKY::F12_32)
                        .Cases("{fr13}", "{vr13}", CSKY::F13_32)
                        .Cases("{fr14}", "{vr14}", CSKY::F14_32)
                        .Cases("{fr15}", "{vr15}", CSKY::F15_32)
                        .Cases("{fr16}", "{vr16}", CSKY::F16_32)
                        .Cases("{fr17}", "{vr17}", CSKY::F17_32)
                        .Cases("{fr18}", "{vr18}", CSKY::F18_32)
                        .Cases("{fr19}", "{vr19}", CSKY::F19_32)
                        .Cases("{fr20}", "{vr20}", CSKY::F20_32)
                        .Cases("{fr21}", "{vr21}", CSKY::F21_32)
                        .Cases("{fr22}", "{vr22}", CSKY::F22_32)
                        .Cases("{fr23}", "{vr23}", CSKY::F23_32)
                        .Cases("{fr24}", "{vr24}", CSKY::F24_32)
                        .Cases("{fr25}", "{vr25}", CSKY::F25_32)
                        .Cases("{fr26}", "{vr26}", CSKY::F26_32)
                        .Cases("{fr27}", "{vr27}", CSKY::F27_32)
                        .Cases("{fr28}", "{vr28}", CSKY::F28_32)
                        .Cases("{fr29}", "{vr29}", CSKY::F29_32)
                        .Cases("{fr30}", "{vr30}", CSKY::F30_32)
                        .Cases("{fr31}", "{vr31}", CSKY::F31_32)
                        .Default(CSKY::NoRegister);
    if (FReg != CSKY::NoRegister) {
      assert(CSKY::F0_32 <= FReg && FReg <= CSKY::F31_32 && "Unknown fp-reg");
      unsigned RegNo = FReg - CSKY::F0_32;
      unsigned DReg = CSKY::F0_64 + RegNo;

      if (Subtarget.hasFPUv2DoubleFloat())
        return std::make_pair(DReg, &CSKY::sFPR64RegClass);
      else if (Subtarget.hasFPUv3DoubleFloat())
        return std::make_pair(DReg, &CSKY::FPR64RegClass);
      else if (Subtarget.hasFPUv2SingleFloat())
        return std::make_pair(FReg, &CSKY::sFPR32RegClass);
      else if (Subtarget.hasFPUv3SingleFloat())
        return std::make_pair(FReg, &CSKY::FPR32RegClass);
    }
  }

  return TargetLowering::getRegForInlineAsmConstraint(TRI, Constraint, VT);
}

static MachineBasicBlock *
emitSelectPseudo(MachineInstr &MI, MachineBasicBlock *BB, unsigned Opcode) {

  const TargetInstrInfo &TII = *BB->getParent()->getSubtarget().getInstrInfo();
  DebugLoc DL = MI.getDebugLoc();

  // To "insert" a SELECT instruction, we actually have to insert the
  // diamond control-flow pattern.  The incoming instruction knows the
  // destination vreg to set, the condition code register to branch on, the
  // true/false values to select between, and a branch opcode to use.
  const BasicBlock *LLVM_BB = BB->getBasicBlock();
  MachineFunction::iterator It = ++BB->getIterator();

  //  thisMBB:
  //  ...
  //   TrueVal = ...
  //   bt32 c, sinkMBB
  //   fallthrough --> copyMBB
  MachineBasicBlock *thisMBB = BB;
  MachineFunction *F = BB->getParent();
  MachineBasicBlock *copyMBB = F->CreateMachineBasicBlock(LLVM_BB);
  MachineBasicBlock *sinkMBB = F->CreateMachineBasicBlock(LLVM_BB);
  F->insert(It, copyMBB);
  F->insert(It, sinkMBB);

  // Transfer the remainder of BB and its successor edges to sinkMBB.
  sinkMBB->splice(sinkMBB->begin(), BB,
                  std::next(MachineBasicBlock::iterator(MI)), BB->end());
  sinkMBB->transferSuccessorsAndUpdatePHIs(BB);

  // Next, add the true and fallthrough blocks as its successors.
  BB->addSuccessor(copyMBB);
  BB->addSuccessor(sinkMBB);

  // bt32 condition, sinkMBB
  BuildMI(BB, DL, TII.get(Opcode))
      .addReg(MI.getOperand(1).getReg())
      .addMBB(sinkMBB);

  //  copyMBB:
  //   %FalseValue = ...
  //   # fallthrough to sinkMBB
  BB = copyMBB;

  // Update machine-CFG edges
  BB->addSuccessor(sinkMBB);

  //  sinkMBB:
  //   %Result = phi [ %TrueValue, thisMBB ], [ %FalseValue, copyMBB ]
  //  ...
  BB = sinkMBB;

  BuildMI(*BB, BB->begin(), DL, TII.get(CSKY::PHI), MI.getOperand(0).getReg())
      .addReg(MI.getOperand(2).getReg())
      .addMBB(thisMBB)
      .addReg(MI.getOperand(3).getReg())
      .addMBB(copyMBB);

  MI.eraseFromParent(); // The pseudo instruction is gone now.

  return BB;
}

MachineBasicBlock *
CSKYTargetLowering::EmitInstrWithCustomInserter(MachineInstr &MI,
                                                MachineBasicBlock *BB) const {
  switch (MI.getOpcode()) {
  default:
    llvm_unreachable("Unexpected instr type to insert");
  case CSKY::FSELS:
  case CSKY::FSELD:
    if (Subtarget.hasE2())
      return emitSelectPseudo(MI, BB, CSKY::BT32);
    else
      return emitSelectPseudo(MI, BB, CSKY::BT16);
  case CSKY::ISEL32:
    return emitSelectPseudo(MI, BB, CSKY::BT32);
  case CSKY::ISEL16:
    return emitSelectPseudo(MI, BB, CSKY::BT16);
  }
}

SDValue CSKYTargetLowering::getTargetConstantPoolValue(ExternalSymbolSDNode *N,
                                                       EVT Ty,
                                                       SelectionDAG &DAG,
                                                       unsigned Flags) const {
  CSKYConstantPoolValue *CPV =
      CSKYConstantPoolSymbol::Create(Type::getInt32Ty(*DAG.getContext()),
                                     N->getSymbol(), 0, getModifier(Flags));

  return DAG.getTargetConstantPool(CPV, Ty);
}

SDValue CSKYTargetLowering::getTargetConstantPoolValue(JumpTableSDNode *N,
                                                       EVT Ty,
                                                       SelectionDAG &DAG,
                                                       unsigned Flags) const {
  CSKYConstantPoolValue *CPV =
      CSKYConstantPoolJT::Create(Type::getInt32Ty(*DAG.getContext()),
                                 N->getIndex(), 0, getModifier(Flags));
  return DAG.getTargetConstantPool(CPV, Ty);
}

SDValue CSKYTargetLowering::getTargetConstantPoolValue(BlockAddressSDNode *N,
                                                       EVT Ty,
                                                       SelectionDAG &DAG,
                                                       unsigned Flags) const {
  assert(N->getOffset() == 0);
  CSKYConstantPoolValue *CPV = CSKYConstantPoolConstant::Create(
      N->getBlockAddress(), CSKYCP::CPBlockAddress, 0, getModifier(Flags),
      false);
  return DAG.getTargetConstantPool(CPV, Ty);
}

SDValue CSKYTargetLowering::getTargetConstantPoolValue(ConstantPoolSDNode *N,
                                                       EVT Ty,
                                                       SelectionDAG &DAG,
                                                       unsigned Flags) const {
  assert(N->getOffset() == 0);
  CSKYConstantPoolValue *CPV = CSKYConstantPoolConstant::Create(
      N->getConstVal(), Type::getInt32Ty(*DAG.getContext()),
      CSKYCP::CPConstPool, 0, getModifier(Flags), false);
  return DAG.getTargetConstantPool(CPV, Ty);
}

SDValue CSKYTargetLowering::getTargetNode(GlobalAddressSDNode *N, SDLoc DL,
                                          EVT Ty, SelectionDAG &DAG,
                                          unsigned Flags) const {
  return DAG.getTargetGlobalAddress(N->getGlobal(), DL, Ty, 0, Flags);
}

SDValue CSKYTargetLowering::getTargetNode(ExternalSymbolSDNode *N, SDLoc DL,
                                          EVT Ty, SelectionDAG &DAG,
                                          unsigned Flags) const {
  return DAG.getTargetExternalSymbol(N->getSymbol(), Ty, Flags);
}

SDValue CSKYTargetLowering::getTargetNode(JumpTableSDNode *N, SDLoc DL, EVT Ty,
                                          SelectionDAG &DAG,
                                          unsigned Flags) const {
  return DAG.getTargetJumpTable(N->getIndex(), Ty, Flags);
}

SDValue CSKYTargetLowering::getTargetNode(BlockAddressSDNode *N, SDLoc DL,
                                          EVT Ty, SelectionDAG &DAG,
                                          unsigned Flags) const {
  return DAG.getTargetBlockAddress(N->getBlockAddress(), Ty, N->getOffset(),
                                   Flags);
}

SDValue CSKYTargetLowering::getTargetNode(ConstantPoolSDNode *N, SDLoc DL,
                                          EVT Ty, SelectionDAG &DAG,
                                          unsigned Flags) const {

  return DAG.getTargetConstantPool(N->getConstVal(), Ty, N->getAlign(),
                                   N->getOffset(), Flags);
}

const char *CSKYTargetLowering::getTargetNodeName(unsigned Opcode) const {
  switch (Opcode) {
  default:
    llvm_unreachable("unknown CSKYISD node");
  case CSKYISD::NIE:
    return "CSKYISD::NIE";
  case CSKYISD::NIR:
    return "CSKYISD::NIR";
  case CSKYISD::RET:
    return "CSKYISD::RET";
  case CSKYISD::CALL:
    return "CSKYISD::CALL";
  case CSKYISD::CALLReg:
    return "CSKYISD::CALLReg";
  case CSKYISD::TAIL:
    return "CSKYISD::TAIL";
  case CSKYISD::TAILReg:
    return "CSKYISD::TAILReg";
  case CSKYISD::LOAD_ADDR:
    return "CSKYISD::LOAD_ADDR";
  case CSKYISD::BITCAST_TO_LOHI:
    return "CSKYISD::BITCAST_TO_LOHI";
  case CSKYISD::BITCAST_FROM_LOHI:
    return "CSKYISD::BITCAST_FROM_LOHI";
  }
}

SDValue CSKYTargetLowering::LowerGlobalAddress(SDValue Op,
                                               SelectionDAG &DAG) const {
  SDLoc DL(Op);
  EVT Ty = Op.getValueType();
  GlobalAddressSDNode *N = cast<GlobalAddressSDNode>(Op);
  int64_t Offset = N->getOffset();

  const GlobalValue *GV = N->getGlobal();
  bool IsLocal = getTargetMachine().shouldAssumeDSOLocal(GV);
  SDValue Addr = getAddr<GlobalAddressSDNode, false>(N, DAG, IsLocal);

  // In order to maximise the opportunity for common subexpression elimination,
  // emit a separate ADD node for the global address offset instead of folding
  // it in the global address node. Later peephole optimisations may choose to
  // fold it back in when profitable.
  if (Offset != 0)
    return DAG.getNode(ISD::ADD, DL, Ty, Addr,
                       DAG.getConstant(Offset, DL, MVT::i32));
  return Addr;
}

SDValue CSKYTargetLowering::LowerExternalSymbol(SDValue Op,
                                                SelectionDAG &DAG) const {
  ExternalSymbolSDNode *N = cast<ExternalSymbolSDNode>(Op);

  return getAddr(N, DAG, false);
}

SDValue CSKYTargetLowering::LowerJumpTable(SDValue Op,
                                           SelectionDAG &DAG) const {
  JumpTableSDNode *N = cast<JumpTableSDNode>(Op);

  return getAddr<JumpTableSDNode, false>(N, DAG);
}

SDValue CSKYTargetLowering::LowerBlockAddress(SDValue Op,
                                              SelectionDAG &DAG) const {
  BlockAddressSDNode *N = cast<BlockAddressSDNode>(Op);

  return getAddr(N, DAG);
}

SDValue CSKYTargetLowering::LowerConstantPool(SDValue Op,
                                              SelectionDAG &DAG) const {
  assert(!Subtarget.hasE2());
  ConstantPoolSDNode *N = cast<ConstantPoolSDNode>(Op);

  return getAddr(N, DAG);
}

SDValue CSKYTargetLowering::LowerVASTART(SDValue Op, SelectionDAG &DAG) const {
  MachineFunction &MF = DAG.getMachineFunction();
  CSKYMachineFunctionInfo *FuncInfo = MF.getInfo<CSKYMachineFunctionInfo>();

  SDLoc DL(Op);
  SDValue FI = DAG.getFrameIndex(FuncInfo->getVarArgsFrameIndex(),
                                 getPointerTy(MF.getDataLayout()));

  // vastart just stores the address of the VarArgsFrameIndex slot into the
  // memory location argument.
  const Value *SV = cast<SrcValueSDNode>(Op.getOperand(2))->getValue();
  return DAG.getStore(Op.getOperand(0), DL, FI, Op.getOperand(1),
                      MachinePointerInfo(SV));
}

SDValue CSKYTargetLowering::LowerFRAMEADDR(SDValue Op,
                                           SelectionDAG &DAG) const {
  const CSKYRegisterInfo &RI = *Subtarget.getRegisterInfo();
  MachineFunction &MF = DAG.getMachineFunction();
  MachineFrameInfo &MFI = MF.getFrameInfo();
  MFI.setFrameAddressIsTaken(true);

  EVT VT = Op.getValueType();
  SDLoc dl(Op);
  unsigned Depth = Op.getConstantOperandVal(0);
  Register FrameReg = RI.getFrameRegister(MF);
  SDValue FrameAddr = DAG.getCopyFromReg(DAG.getEntryNode(), dl, FrameReg, VT);
  while (Depth--)
    FrameAddr = DAG.getLoad(VT, dl, DAG.getEntryNode(), FrameAddr,
                            MachinePointerInfo());
  return FrameAddr;
}

SDValue CSKYTargetLowering::LowerRETURNADDR(SDValue Op,
                                            SelectionDAG &DAG) const {
  const CSKYRegisterInfo &RI = *Subtarget.getRegisterInfo();
  MachineFunction &MF = DAG.getMachineFunction();
  MachineFrameInfo &MFI = MF.getFrameInfo();
  MFI.setReturnAddressIsTaken(true);

  if (verifyReturnAddressArgumentIsConstant(Op, DAG))
    return SDValue();

  EVT VT = Op.getValueType();
  SDLoc dl(Op);
  unsigned Depth = Op.getConstantOperandVal(0);
  if (Depth) {
    SDValue FrameAddr = LowerFRAMEADDR(Op, DAG);
    SDValue Offset = DAG.getConstant(4, dl, MVT::i32);
    return DAG.getLoad(VT, dl, DAG.getEntryNode(),
                       DAG.getNode(ISD::ADD, dl, VT, FrameAddr, Offset),
                       MachinePointerInfo());
  }
  // Return the value of the return address register, marking it an implicit
  // live-in.
  unsigned Reg = MF.addLiveIn(RI.getRARegister(), getRegClassFor(MVT::i32));
  return DAG.getCopyFromReg(DAG.getEntryNode(), dl, Reg, VT);
}

Register CSKYTargetLowering::getExceptionPointerRegister(
    const Constant *PersonalityFn) const {
  return CSKY::R0;
}

Register CSKYTargetLowering::getExceptionSelectorRegister(
    const Constant *PersonalityFn) const {
  return CSKY::R1;
}

SDValue CSKYTargetLowering::LowerGlobalTLSAddress(SDValue Op,
                                                  SelectionDAG &DAG) const {
  SDLoc DL(Op);
  EVT Ty = Op.getValueType();
  GlobalAddressSDNode *N = cast<GlobalAddressSDNode>(Op);
  int64_t Offset = N->getOffset();
  MVT XLenVT = MVT::i32;

  TLSModel::Model Model = getTargetMachine().getTLSModel(N->getGlobal());
  SDValue Addr;
  switch (Model) {
  case TLSModel::LocalExec:
    Addr = getStaticTLSAddr(N, DAG, /*UseGOT=*/false);
    break;
  case TLSModel::InitialExec:
    Addr = getStaticTLSAddr(N, DAG, /*UseGOT=*/true);
    break;
  case TLSModel::LocalDynamic:
  case TLSModel::GeneralDynamic:
    Addr = getDynamicTLSAddr(N, DAG);
    break;
  }

  // In order to maximise the opportunity for common subexpression elimination,
  // emit a separate ADD node for the global address offset instead of folding
  // it in the global address node. Later peephole optimisations may choose to
  // fold it back in when profitable.
  if (Offset != 0)
    return DAG.getNode(ISD::ADD, DL, Ty, Addr,
                       DAG.getConstant(Offset, DL, XLenVT));
  return Addr;
}

SDValue CSKYTargetLowering::getStaticTLSAddr(GlobalAddressSDNode *N,
                                             SelectionDAG &DAG,
                                             bool UseGOT) const {
  MachineFunction &MF = DAG.getMachineFunction();
  CSKYMachineFunctionInfo *CFI = MF.getInfo<CSKYMachineFunctionInfo>();

  unsigned CSKYPCLabelIndex = CFI->createPICLabelUId();

  SDLoc DL(N);
  EVT Ty = getPointerTy(DAG.getDataLayout());

  CSKYCP::CSKYCPModifier Flag = UseGOT ? CSKYCP::TLSIE : CSKYCP::TLSLE;
  bool AddCurrentAddr = UseGOT ? true : false;
  unsigned char PCAjust = UseGOT ? 4 : 0;

  CSKYConstantPoolValue *CPV =
      CSKYConstantPoolConstant::Create(N->getGlobal(), CSKYCP::CPValue, PCAjust,
                                       Flag, AddCurrentAddr, CSKYPCLabelIndex);
  SDValue CAddr = DAG.getTargetConstantPool(CPV, Ty);

  SDValue Load;
  if (UseGOT) {
    SDValue PICLabel = DAG.getTargetConstant(CSKYPCLabelIndex, DL, MVT::i32);
    auto *LRWGRS = DAG.getMachineNode(CSKY::PseudoTLSLA32, DL, {Ty, Ty},
                                      {CAddr, PICLabel});
    auto LRWADDGRS =
        DAG.getNode(ISD::ADD, DL, Ty, SDValue(LRWGRS, 0), SDValue(LRWGRS, 1));
    Load = DAG.getLoad(Ty, DL, DAG.getEntryNode(), LRWADDGRS,
                       MachinePointerInfo(N->getGlobal()));
  } else {
    Load = SDValue(DAG.getMachineNode(CSKY::LRW32, DL, Ty, CAddr), 0);
  }

  // Add the thread pointer.
  SDValue TPReg = DAG.getRegister(CSKY::R31, MVT::i32);
  return DAG.getNode(ISD::ADD, DL, Ty, Load, TPReg);
}

SDValue CSKYTargetLowering::getDynamicTLSAddr(GlobalAddressSDNode *N,
                                              SelectionDAG &DAG) const {
  MachineFunction &MF = DAG.getMachineFunction();
  CSKYMachineFunctionInfo *CFI = MF.getInfo<CSKYMachineFunctionInfo>();

  unsigned CSKYPCLabelIndex = CFI->createPICLabelUId();

  SDLoc DL(N);
  EVT Ty = getPointerTy(DAG.getDataLayout());
  IntegerType *CallTy = Type::getIntNTy(*DAG.getContext(), Ty.getSizeInBits());

  CSKYConstantPoolValue *CPV =
      CSKYConstantPoolConstant::Create(N->getGlobal(), CSKYCP::CPValue, 4,
                                       CSKYCP::TLSGD, true, CSKYPCLabelIndex);
  SDValue Addr = DAG.getTargetConstantPool(CPV, Ty);
  SDValue PICLabel = DAG.getTargetConstant(CSKYPCLabelIndex, DL, MVT::i32);

  auto *LRWGRS =
      DAG.getMachineNode(CSKY::PseudoTLSLA32, DL, {Ty, Ty}, {Addr, PICLabel});

  auto Load =
      DAG.getNode(ISD::ADD, DL, Ty, SDValue(LRWGRS, 0), SDValue(LRWGRS, 1));

  // Prepare argument list to generate call.
  ArgListTy Args;
  ArgListEntry Entry;
  Entry.Node = Load;
  Entry.Ty = CallTy;
  Args.push_back(Entry);

  // Setup call to __tls_get_addr.
  TargetLowering::CallLoweringInfo CLI(DAG);
  CLI.setDebugLoc(DL)
      .setChain(DAG.getEntryNode())
      .setLibCallee(CallingConv::C, CallTy,
                    DAG.getExternalSymbol("__tls_get_addr", Ty),
                    std::move(Args));
  SDValue V = LowerCallTo(CLI).first;

  return V;
}

bool CSKYTargetLowering::decomposeMulByConstant(LLVMContext &Context, EVT VT,
                                                SDValue C) const {
  if (!VT.isScalarInteger())
    return false;

  // Omit if data size exceeds.
  if (VT.getSizeInBits() > Subtarget.XLen)
    return false;

  if (auto *ConstNode = dyn_cast<ConstantSDNode>(C.getNode())) {
    const APInt &Imm = ConstNode->getAPIntValue();
    // Break MULT to LSLI + ADDU/SUBU.
    if ((Imm + 1).isPowerOf2() || (Imm - 1).isPowerOf2() ||
        (1 - Imm).isPowerOf2())
      return true;
    // Only break MULT for sub targets without MULT32, since an extra
    // instruction will be generated against the above 3 cases. We leave it
    // unchanged on sub targets with MULT32, since not sure it is better.
    if (!Subtarget.hasE2() && (-1 - Imm).isPowerOf2())
      return true;
    // Break (MULT x, imm) to ([IXH32|IXW32|IXD32] (LSLI32 x, i0), x) when
    // imm=(1<<i0)+[2|4|8] and imm has to be composed via a MOVIH32/ORI32 pair.
    if (Imm.ugt(0xffff) && ((Imm - 2).isPowerOf2() || (Imm - 4).isPowerOf2()) &&
        Subtarget.hasE2())
      return true;
    if (Imm.ugt(0xffff) && (Imm - 8).isPowerOf2() && Subtarget.has2E3())
      return true;
  }

  return false;
}

bool CSKYTargetLowering::isCheapToSpeculateCttz(Type *Ty) const {
  return Subtarget.has2E3();
}

bool CSKYTargetLowering::isCheapToSpeculateCtlz(Type *Ty) const {
  return Subtarget.hasE2();
}
