181ad6265SDimitry Andric //=- LoongArchISelLowering.h - LoongArch DAG Lowering Interface -*- C++ -*-===// 281ad6265SDimitry Andric // 381ad6265SDimitry Andric // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 481ad6265SDimitry Andric // See https://llvm.org/LICENSE.txt for license information. 581ad6265SDimitry Andric // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 681ad6265SDimitry Andric // 781ad6265SDimitry Andric //===----------------------------------------------------------------------===// 881ad6265SDimitry Andric // 981ad6265SDimitry Andric // This file defines the interfaces that LoongArch uses to lower LLVM code into 1081ad6265SDimitry Andric // a selection DAG. 1181ad6265SDimitry Andric // 1281ad6265SDimitry Andric //===----------------------------------------------------------------------===// 1381ad6265SDimitry Andric 1481ad6265SDimitry Andric #ifndef LLVM_LIB_TARGET_LOONGARCH_LOONGARCHISELLOWERING_H 1581ad6265SDimitry Andric #define LLVM_LIB_TARGET_LOONGARCH_LOONGARCHISELLOWERING_H 1681ad6265SDimitry Andric 1781ad6265SDimitry Andric #include "LoongArch.h" 1881ad6265SDimitry Andric #include "llvm/CodeGen/CallingConvLower.h" 1981ad6265SDimitry Andric #include "llvm/CodeGen/SelectionDAG.h" 2081ad6265SDimitry Andric #include "llvm/CodeGen/TargetLowering.h" 2181ad6265SDimitry Andric 2281ad6265SDimitry Andric namespace llvm { 2381ad6265SDimitry Andric class LoongArchSubtarget; 2481ad6265SDimitry Andric namespace LoongArchISD { 2581ad6265SDimitry Andric enum NodeType : unsigned { 2681ad6265SDimitry Andric FIRST_NUMBER = ISD::BUILTIN_OP_END, 2781ad6265SDimitry Andric 2881ad6265SDimitry Andric // TODO: add more LoongArchISDs 29753f127fSDimitry Andric CALL, 3081ad6265SDimitry Andric RET, 31bdd1243dSDimitry Andric TAIL, 32bdd1243dSDimitry Andric 3381ad6265SDimitry Andric // 32-bit shifts, directly matching the semantics of the named LoongArch 3481ad6265SDimitry Andric // instructions. 3581ad6265SDimitry Andric SLL_W, 3681ad6265SDimitry Andric SRA_W, 3781ad6265SDimitry Andric SRL_W, 3881ad6265SDimitry Andric 39bdd1243dSDimitry Andric ROTL_W, 40bdd1243dSDimitry Andric ROTR_W, 41bdd1243dSDimitry Andric 42753f127fSDimitry Andric // FPR<->GPR transfer operations 43753f127fSDimitry Andric MOVGR2FR_W_LA64, 44753f127fSDimitry Andric MOVFR2GR_S_LA64, 45bdd1243dSDimitry Andric MOVFCSR2GR, 46bdd1243dSDimitry Andric MOVGR2FCSR, 47753f127fSDimitry Andric 48753f127fSDimitry Andric FTINT, 49753f127fSDimitry Andric 50bdd1243dSDimitry Andric // Bit counting operations 51bdd1243dSDimitry Andric CLZ_W, 52bdd1243dSDimitry Andric CTZ_W, 53bdd1243dSDimitry Andric 54753f127fSDimitry Andric BSTRINS, 5581ad6265SDimitry Andric BSTRPICK, 5681ad6265SDimitry Andric 57bdd1243dSDimitry Andric // Byte-swapping and bit-reversal 58bdd1243dSDimitry Andric REVB_2H, 59bdd1243dSDimitry Andric REVB_2W, 60bdd1243dSDimitry Andric BITREV_4B, 61bdd1243dSDimitry Andric BITREV_W, 62bdd1243dSDimitry Andric 63bdd1243dSDimitry Andric // Intrinsic operations start ============================================ 64bdd1243dSDimitry Andric BREAK, 65bdd1243dSDimitry Andric CACOP_D, 66bdd1243dSDimitry Andric CACOP_W, 67bdd1243dSDimitry Andric DBAR, 68bdd1243dSDimitry Andric IBAR, 69bdd1243dSDimitry Andric SYSCALL, 70bdd1243dSDimitry Andric 71bdd1243dSDimitry Andric // CRC check operations 72bdd1243dSDimitry Andric CRC_W_B_W, 73bdd1243dSDimitry Andric CRC_W_H_W, 74bdd1243dSDimitry Andric CRC_W_W_W, 75bdd1243dSDimitry Andric CRC_W_D_W, 76bdd1243dSDimitry Andric CRCC_W_B_W, 77bdd1243dSDimitry Andric CRCC_W_H_W, 78bdd1243dSDimitry Andric CRCC_W_W_W, 79bdd1243dSDimitry Andric CRCC_W_D_W, 80bdd1243dSDimitry Andric 81bdd1243dSDimitry Andric CSRRD, 8206c3fb27SDimitry Andric 8306c3fb27SDimitry Andric // Write new value to CSR and return old value. 8406c3fb27SDimitry Andric // Operand 0: A chain pointer. 8506c3fb27SDimitry Andric // Operand 1: The new value to write. 8606c3fb27SDimitry Andric // Operand 2: The address of the required CSR. 8706c3fb27SDimitry Andric // Result 0: The old value of the CSR. 8806c3fb27SDimitry Andric // Result 1: The new chain pointer. 89bdd1243dSDimitry Andric CSRWR, 9006c3fb27SDimitry Andric 9106c3fb27SDimitry Andric // Similar to CSRWR but with a write mask. 9206c3fb27SDimitry Andric // Operand 0: A chain pointer. 9306c3fb27SDimitry Andric // Operand 1: The new value to write. 9406c3fb27SDimitry Andric // Operand 2: The write mask. 9506c3fb27SDimitry Andric // Operand 3: The address of the required CSR. 9606c3fb27SDimitry Andric // Result 0: The old value of the CSR. 9706c3fb27SDimitry Andric // Result 1: The new chain pointer. 98bdd1243dSDimitry Andric CSRXCHG, 99bdd1243dSDimitry Andric 100bdd1243dSDimitry Andric // IOCSR access operations 101bdd1243dSDimitry Andric IOCSRRD_B, 102bdd1243dSDimitry Andric IOCSRRD_W, 103bdd1243dSDimitry Andric IOCSRRD_H, 104bdd1243dSDimitry Andric IOCSRRD_D, 105bdd1243dSDimitry Andric IOCSRWR_B, 106bdd1243dSDimitry Andric IOCSRWR_H, 107bdd1243dSDimitry Andric IOCSRWR_W, 108bdd1243dSDimitry Andric IOCSRWR_D, 109bdd1243dSDimitry Andric 110bdd1243dSDimitry Andric // Read CPU configuration information operation 111bdd1243dSDimitry Andric CPUCFG, 1125f757f3fSDimitry Andric 1135f757f3fSDimitry Andric // Vector Shuffle 1145f757f3fSDimitry Andric VREPLVE, 1155f757f3fSDimitry Andric 1165f757f3fSDimitry Andric // Extended vector element extraction 1175f757f3fSDimitry Andric VPICK_SEXT_ELT, 1185f757f3fSDimitry Andric VPICK_ZEXT_ELT, 1195f757f3fSDimitry Andric 1205f757f3fSDimitry Andric // Vector comparisons 1215f757f3fSDimitry Andric VALL_ZERO, 1225f757f3fSDimitry Andric VANY_ZERO, 1235f757f3fSDimitry Andric VALL_NONZERO, 1245f757f3fSDimitry Andric VANY_NONZERO, 1255f757f3fSDimitry Andric 126bdd1243dSDimitry Andric // Intrinsic operations end ============================================= 12781ad6265SDimitry Andric }; 128972a253aSDimitry Andric } // end namespace LoongArchISD 12981ad6265SDimitry Andric 13081ad6265SDimitry Andric class LoongArchTargetLowering : public TargetLowering { 13181ad6265SDimitry Andric const LoongArchSubtarget &Subtarget; 13281ad6265SDimitry Andric 13381ad6265SDimitry Andric public: 13481ad6265SDimitry Andric explicit LoongArchTargetLowering(const TargetMachine &TM, 13581ad6265SDimitry Andric const LoongArchSubtarget &STI); 13681ad6265SDimitry Andric 13781ad6265SDimitry Andric const LoongArchSubtarget &getSubtarget() const { return Subtarget; } 13881ad6265SDimitry Andric 139bdd1243dSDimitry Andric bool isOffsetFoldingLegal(const GlobalAddressSDNode *GA) const override; 140bdd1243dSDimitry Andric 14181ad6265SDimitry Andric // Provide custom lowering hooks for some operations. 14281ad6265SDimitry Andric SDValue LowerOperation(SDValue Op, SelectionDAG &DAG) const override; 14381ad6265SDimitry Andric void ReplaceNodeResults(SDNode *N, SmallVectorImpl<SDValue> &Results, 14481ad6265SDimitry Andric SelectionDAG &DAG) const override; 14581ad6265SDimitry Andric 14681ad6265SDimitry Andric SDValue PerformDAGCombine(SDNode *N, DAGCombinerInfo &DCI) const override; 14781ad6265SDimitry Andric 14881ad6265SDimitry Andric // This method returns the name of a target specific DAG node. 14981ad6265SDimitry Andric const char *getTargetNodeName(unsigned Opcode) const override; 15081ad6265SDimitry Andric 15181ad6265SDimitry Andric // Lower incoming arguments, copy physregs into vregs. 15281ad6265SDimitry Andric SDValue LowerFormalArguments(SDValue Chain, CallingConv::ID CallConv, 15381ad6265SDimitry Andric bool IsVarArg, 15481ad6265SDimitry Andric const SmallVectorImpl<ISD::InputArg> &Ins, 15581ad6265SDimitry Andric const SDLoc &DL, SelectionDAG &DAG, 15681ad6265SDimitry Andric SmallVectorImpl<SDValue> &InVals) const override; 15781ad6265SDimitry Andric bool CanLowerReturn(CallingConv::ID CallConv, MachineFunction &MF, 15881ad6265SDimitry Andric bool IsVarArg, 15981ad6265SDimitry Andric const SmallVectorImpl<ISD::OutputArg> &Outs, 16081ad6265SDimitry Andric LLVMContext &Context) const override; 16181ad6265SDimitry Andric SDValue LowerReturn(SDValue Chain, CallingConv::ID CallConv, bool IsVarArg, 16281ad6265SDimitry Andric const SmallVectorImpl<ISD::OutputArg> &Outs, 16381ad6265SDimitry Andric const SmallVectorImpl<SDValue> &OutVals, const SDLoc &DL, 16481ad6265SDimitry Andric SelectionDAG &DAG) const override; 165753f127fSDimitry Andric SDValue LowerCall(TargetLowering::CallLoweringInfo &CLI, 166753f127fSDimitry Andric SmallVectorImpl<SDValue> &InVals) const override; 167bdd1243dSDimitry Andric bool isCheapToSpeculateCttz(Type *Ty) const override; 168bdd1243dSDimitry Andric bool isCheapToSpeculateCtlz(Type *Ty) const override; 169bdd1243dSDimitry Andric bool hasAndNot(SDValue Y) const override; 170bdd1243dSDimitry Andric TargetLowering::AtomicExpansionKind 171bdd1243dSDimitry Andric shouldExpandAtomicRMWInIR(AtomicRMWInst *AI) const override; 172bdd1243dSDimitry Andric 173bdd1243dSDimitry Andric Value *emitMaskedAtomicRMWIntrinsic(IRBuilderBase &Builder, AtomicRMWInst *AI, 174bdd1243dSDimitry Andric Value *AlignedAddr, Value *Incr, 175bdd1243dSDimitry Andric Value *Mask, Value *ShiftAmt, 176bdd1243dSDimitry Andric AtomicOrdering Ord) const override; 177bdd1243dSDimitry Andric 178bdd1243dSDimitry Andric EVT getSetCCResultType(const DataLayout &DL, LLVMContext &Context, 179bdd1243dSDimitry Andric EVT VT) const override; 180bdd1243dSDimitry Andric TargetLowering::AtomicExpansionKind 181bdd1243dSDimitry Andric shouldExpandAtomicCmpXchgInIR(AtomicCmpXchgInst *CI) const override; 182bdd1243dSDimitry Andric Value *emitMaskedAtomicCmpXchgIntrinsic(IRBuilderBase &Builder, 183bdd1243dSDimitry Andric AtomicCmpXchgInst *CI, 184bdd1243dSDimitry Andric Value *AlignedAddr, Value *CmpVal, 185bdd1243dSDimitry Andric Value *NewVal, Value *Mask, 186bdd1243dSDimitry Andric AtomicOrdering Ord) const override; 187bdd1243dSDimitry Andric 188bdd1243dSDimitry Andric bool getTgtMemIntrinsic(IntrinsicInfo &Info, const CallInst &I, 189bdd1243dSDimitry Andric MachineFunction &MF, 190bdd1243dSDimitry Andric unsigned Intrinsic) const override; 191bdd1243dSDimitry Andric 192bdd1243dSDimitry Andric bool isFMAFasterThanFMulAndFAdd(const MachineFunction &MF, 193bdd1243dSDimitry Andric EVT VT) const override; 194bdd1243dSDimitry Andric 195bdd1243dSDimitry Andric Register 196bdd1243dSDimitry Andric getExceptionPointerRegister(const Constant *PersonalityFn) const override; 197bdd1243dSDimitry Andric 198bdd1243dSDimitry Andric Register 199bdd1243dSDimitry Andric getExceptionSelectorRegister(const Constant *PersonalityFn) const override; 200bdd1243dSDimitry Andric 201bdd1243dSDimitry Andric ISD::NodeType getExtendForAtomicOps() const override { 202bdd1243dSDimitry Andric return ISD::SIGN_EXTEND; 203bdd1243dSDimitry Andric } 204bdd1243dSDimitry Andric 205bdd1243dSDimitry Andric Register getRegisterByName(const char *RegName, LLT VT, 206bdd1243dSDimitry Andric const MachineFunction &MF) const override; 207bdd1243dSDimitry Andric bool mayBeEmittedAsTailCall(const CallInst *CI) const override; 208bdd1243dSDimitry Andric 209bdd1243dSDimitry Andric bool decomposeMulByConstant(LLVMContext &Context, EVT VT, 210bdd1243dSDimitry Andric SDValue C) const override; 21181ad6265SDimitry Andric 21206c3fb27SDimitry Andric bool isUsedByReturnOnly(SDNode *N, SDValue &Chain) const override; 21306c3fb27SDimitry Andric 21406c3fb27SDimitry Andric bool isLegalAddressingMode(const DataLayout &DL, const AddrMode &AM, Type *Ty, 21506c3fb27SDimitry Andric unsigned AS, 21606c3fb27SDimitry Andric Instruction *I = nullptr) const override; 21706c3fb27SDimitry Andric 21806c3fb27SDimitry Andric bool isLegalICmpImmediate(int64_t Imm) const override; 21906c3fb27SDimitry Andric bool isLegalAddImmediate(int64_t Imm) const override; 22006c3fb27SDimitry Andric bool isZExtFree(SDValue Val, EVT VT2) const override; 22106c3fb27SDimitry Andric bool isSExtCheaperThanZExt(EVT SrcVT, EVT DstVT) const override; 22206c3fb27SDimitry Andric 22306c3fb27SDimitry Andric bool hasAndNotCompare(SDValue Y) const override; 22406c3fb27SDimitry Andric 22506c3fb27SDimitry Andric bool convertSelectOfConstantsToMath(EVT VT) const override { return true; } 22606c3fb27SDimitry Andric 22706c3fb27SDimitry Andric bool allowsMisalignedMemoryAccesses( 22806c3fb27SDimitry Andric EVT VT, unsigned AddrSpace = 0, Align Alignment = Align(1), 22906c3fb27SDimitry Andric MachineMemOperand::Flags Flags = MachineMemOperand::MONone, 23006c3fb27SDimitry Andric unsigned *Fast = nullptr) const override; 23106c3fb27SDimitry Andric 2325f757f3fSDimitry Andric bool isShuffleMaskLegal(ArrayRef<int> Mask, EVT VT) const override { 2335f757f3fSDimitry Andric return false; 2345f757f3fSDimitry Andric } 2355f757f3fSDimitry Andric 23681ad6265SDimitry Andric private: 23781ad6265SDimitry Andric /// Target-specific function used to lower LoongArch calling conventions. 238bdd1243dSDimitry Andric typedef bool LoongArchCCAssignFn(const DataLayout &DL, LoongArchABI::ABI ABI, 239bdd1243dSDimitry Andric unsigned ValNo, MVT ValVT, 24081ad6265SDimitry Andric CCValAssign::LocInfo LocInfo, 241bdd1243dSDimitry Andric ISD::ArgFlagsTy ArgFlags, CCState &State, 242bdd1243dSDimitry Andric bool IsFixed, bool IsReg, Type *OrigTy); 24381ad6265SDimitry Andric 244bdd1243dSDimitry Andric void analyzeInputArgs(MachineFunction &MF, CCState &CCInfo, 245bdd1243dSDimitry Andric const SmallVectorImpl<ISD::InputArg> &Ins, bool IsRet, 24681ad6265SDimitry Andric LoongArchCCAssignFn Fn) const; 247bdd1243dSDimitry Andric void analyzeOutputArgs(MachineFunction &MF, CCState &CCInfo, 24881ad6265SDimitry Andric const SmallVectorImpl<ISD::OutputArg> &Outs, 249bdd1243dSDimitry Andric bool IsRet, CallLoweringInfo *CLI, 25081ad6265SDimitry Andric LoongArchCCAssignFn Fn) const; 25181ad6265SDimitry Andric 252bdd1243dSDimitry Andric template <class NodeTy> 253bdd1243dSDimitry Andric SDValue getAddr(NodeTy *N, SelectionDAG &DAG, bool IsLocal = true) const; 254bdd1243dSDimitry Andric SDValue getStaticTLSAddr(GlobalAddressSDNode *N, SelectionDAG &DAG, 25506c3fb27SDimitry Andric unsigned Opc, bool Large = false) const; 256bdd1243dSDimitry Andric SDValue getDynamicTLSAddr(GlobalAddressSDNode *N, SelectionDAG &DAG, 25706c3fb27SDimitry Andric unsigned Opc, bool Large = false) const; 258753f127fSDimitry Andric SDValue lowerGlobalAddress(SDValue Op, SelectionDAG &DAG) const; 259bdd1243dSDimitry Andric SDValue lowerBlockAddress(SDValue Op, SelectionDAG &DAG) const; 260bdd1243dSDimitry Andric SDValue lowerJumpTable(SDValue Op, SelectionDAG &DAG) const; 261bdd1243dSDimitry Andric SDValue lowerGlobalTLSAddress(SDValue Op, SelectionDAG &DAG) const; 26281ad6265SDimitry Andric SDValue lowerShiftLeftParts(SDValue Op, SelectionDAG &DAG) const; 26381ad6265SDimitry Andric SDValue lowerShiftRightParts(SDValue Op, SelectionDAG &DAG, bool IsSRA) const; 264753f127fSDimitry Andric 265753f127fSDimitry Andric MachineBasicBlock * 266753f127fSDimitry Andric EmitInstrWithCustomInserter(MachineInstr &MI, 267753f127fSDimitry Andric MachineBasicBlock *BB) const override; 2685f757f3fSDimitry Andric SDValue lowerATOMIC_FENCE(SDValue Op, SelectionDAG &DAG) const; 269753f127fSDimitry Andric SDValue lowerConstantPool(SDValue Op, SelectionDAG &DAG) const; 270bdd1243dSDimitry Andric SDValue lowerEH_DWARF_CFA(SDValue Op, SelectionDAG &DAG) const; 271753f127fSDimitry Andric SDValue lowerFP_TO_SINT(SDValue Op, SelectionDAG &DAG) const; 272753f127fSDimitry Andric SDValue lowerBITCAST(SDValue Op, SelectionDAG &DAG) const; 273753f127fSDimitry Andric SDValue lowerUINT_TO_FP(SDValue Op, SelectionDAG &DAG) const; 274bdd1243dSDimitry Andric SDValue lowerSINT_TO_FP(SDValue Op, SelectionDAG &DAG) const; 275bdd1243dSDimitry Andric SDValue lowerVASTART(SDValue Op, SelectionDAG &DAG) const; 276bdd1243dSDimitry Andric SDValue lowerINTRINSIC_WO_CHAIN(SDValue Op, SelectionDAG &DAG) const; 277bdd1243dSDimitry Andric SDValue lowerINTRINSIC_W_CHAIN(SDValue Op, SelectionDAG &DAG) const; 278bdd1243dSDimitry Andric SDValue lowerINTRINSIC_VOID(SDValue Op, SelectionDAG &DAG) const; 279bdd1243dSDimitry Andric SDValue lowerFRAMEADDR(SDValue Op, SelectionDAG &DAG) const; 280bdd1243dSDimitry Andric SDValue lowerRETURNADDR(SDValue Op, SelectionDAG &DAG) const; 281bdd1243dSDimitry Andric SDValue lowerWRITE_REGISTER(SDValue Op, SelectionDAG &DAG) const; 282*647cbc5dSDimitry Andric SDValue lowerEXTRACT_VECTOR_ELT(SDValue Op, SelectionDAG &DAG) const; 2835f757f3fSDimitry Andric SDValue lowerINSERT_VECTOR_ELT(SDValue Op, SelectionDAG &DAG) const; 2845f757f3fSDimitry Andric SDValue lowerBUILD_VECTOR(SDValue Op, SelectionDAG &DAG) const; 2855f757f3fSDimitry Andric SDValue lowerVECTOR_SHUFFLE(SDValue Op, SelectionDAG &DAG) const; 286753f127fSDimitry Andric 287753f127fSDimitry Andric bool isFPImmLegal(const APFloat &Imm, EVT VT, 288753f127fSDimitry Andric bool ForCodeSize) const override; 289753f127fSDimitry Andric 290bdd1243dSDimitry Andric bool shouldInsertFencesForAtomic(const Instruction *I) const override; 291bdd1243dSDimitry Andric 292bdd1243dSDimitry Andric ConstraintType getConstraintType(StringRef Constraint) const override; 293bdd1243dSDimitry Andric 2945f757f3fSDimitry Andric InlineAsm::ConstraintCode 2955f757f3fSDimitry Andric getInlineAsmMemConstraint(StringRef ConstraintCode) const override; 296bdd1243dSDimitry Andric 297bdd1243dSDimitry Andric std::pair<unsigned, const TargetRegisterClass *> 298bdd1243dSDimitry Andric getRegForInlineAsmConstraint(const TargetRegisterInfo *TRI, 299bdd1243dSDimitry Andric StringRef Constraint, MVT VT) const override; 300bdd1243dSDimitry Andric 3015f757f3fSDimitry Andric void LowerAsmOperandForConstraint(SDValue Op, StringRef Constraint, 302bdd1243dSDimitry Andric std::vector<SDValue> &Ops, 303bdd1243dSDimitry Andric SelectionDAG &DAG) const override; 304bdd1243dSDimitry Andric 305bdd1243dSDimitry Andric bool isEligibleForTailCallOptimization( 306bdd1243dSDimitry Andric CCState &CCInfo, CallLoweringInfo &CLI, MachineFunction &MF, 307bdd1243dSDimitry Andric const SmallVectorImpl<CCValAssign> &ArgLocs) const; 30881ad6265SDimitry Andric }; 30981ad6265SDimitry Andric 31081ad6265SDimitry Andric } // end namespace llvm 31181ad6265SDimitry Andric 31281ad6265SDimitry Andric #endif // LLVM_LIB_TARGET_LOONGARCH_LOONGARCHISELLOWERING_H 313