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 struct LoongArchRegisterInfo; 2581ad6265SDimitry Andric namespace LoongArchISD { 2681ad6265SDimitry Andric enum NodeType : unsigned { 2781ad6265SDimitry Andric FIRST_NUMBER = ISD::BUILTIN_OP_END, 2881ad6265SDimitry Andric 2981ad6265SDimitry Andric // TODO: add more LoongArchISDs 30753f127fSDimitry Andric CALL, 3181ad6265SDimitry Andric RET, 32bdd1243dSDimitry Andric TAIL, 33bdd1243dSDimitry Andric 3481ad6265SDimitry Andric // 32-bit shifts, directly matching the semantics of the named LoongArch 3581ad6265SDimitry Andric // instructions. 3681ad6265SDimitry Andric SLL_W, 3781ad6265SDimitry Andric SRA_W, 3881ad6265SDimitry Andric SRL_W, 3981ad6265SDimitry Andric 40bdd1243dSDimitry Andric ROTL_W, 41bdd1243dSDimitry Andric ROTR_W, 42bdd1243dSDimitry Andric 43753f127fSDimitry Andric // FPR<->GPR transfer operations 44753f127fSDimitry Andric MOVGR2FR_W_LA64, 45753f127fSDimitry Andric MOVFR2GR_S_LA64, 46bdd1243dSDimitry Andric MOVFCSR2GR, 47bdd1243dSDimitry Andric MOVGR2FCSR, 48753f127fSDimitry Andric 49753f127fSDimitry Andric FTINT, 50753f127fSDimitry Andric 51bdd1243dSDimitry Andric // Bit counting operations 52bdd1243dSDimitry Andric CLZ_W, 53bdd1243dSDimitry Andric CTZ_W, 54bdd1243dSDimitry Andric 55753f127fSDimitry Andric BSTRINS, 5681ad6265SDimitry Andric BSTRPICK, 5781ad6265SDimitry Andric 58bdd1243dSDimitry Andric // Byte-swapping and bit-reversal 59bdd1243dSDimitry Andric REVB_2H, 60bdd1243dSDimitry Andric REVB_2W, 61bdd1243dSDimitry Andric BITREV_4B, 62bdd1243dSDimitry Andric BITREV_W, 63bdd1243dSDimitry Andric 64bdd1243dSDimitry Andric // Intrinsic operations start ============================================ 65bdd1243dSDimitry Andric BREAK, 66bdd1243dSDimitry Andric CACOP_D, 67bdd1243dSDimitry Andric CACOP_W, 68bdd1243dSDimitry Andric DBAR, 69bdd1243dSDimitry Andric IBAR, 70bdd1243dSDimitry Andric SYSCALL, 71bdd1243dSDimitry Andric 72bdd1243dSDimitry Andric // CRC check operations 73bdd1243dSDimitry Andric CRC_W_B_W, 74bdd1243dSDimitry Andric CRC_W_H_W, 75bdd1243dSDimitry Andric CRC_W_W_W, 76bdd1243dSDimitry Andric CRC_W_D_W, 77bdd1243dSDimitry Andric CRCC_W_B_W, 78bdd1243dSDimitry Andric CRCC_W_H_W, 79bdd1243dSDimitry Andric CRCC_W_W_W, 80bdd1243dSDimitry Andric CRCC_W_D_W, 81bdd1243dSDimitry Andric 82bdd1243dSDimitry Andric CSRRD, 83*06c3fb27SDimitry Andric 84*06c3fb27SDimitry Andric // Write new value to CSR and return old value. 85*06c3fb27SDimitry Andric // Operand 0: A chain pointer. 86*06c3fb27SDimitry Andric // Operand 1: The new value to write. 87*06c3fb27SDimitry Andric // Operand 2: The address of the required CSR. 88*06c3fb27SDimitry Andric // Result 0: The old value of the CSR. 89*06c3fb27SDimitry Andric // Result 1: The new chain pointer. 90bdd1243dSDimitry Andric CSRWR, 91*06c3fb27SDimitry Andric 92*06c3fb27SDimitry Andric // Similar to CSRWR but with a write mask. 93*06c3fb27SDimitry Andric // Operand 0: A chain pointer. 94*06c3fb27SDimitry Andric // Operand 1: The new value to write. 95*06c3fb27SDimitry Andric // Operand 2: The write mask. 96*06c3fb27SDimitry Andric // Operand 3: The address of the required CSR. 97*06c3fb27SDimitry Andric // Result 0: The old value of the CSR. 98*06c3fb27SDimitry Andric // Result 1: The new chain pointer. 99bdd1243dSDimitry Andric CSRXCHG, 100bdd1243dSDimitry Andric 101bdd1243dSDimitry Andric // IOCSR access operations 102bdd1243dSDimitry Andric IOCSRRD_B, 103bdd1243dSDimitry Andric IOCSRRD_W, 104bdd1243dSDimitry Andric IOCSRRD_H, 105bdd1243dSDimitry Andric IOCSRRD_D, 106bdd1243dSDimitry Andric IOCSRWR_B, 107bdd1243dSDimitry Andric IOCSRWR_H, 108bdd1243dSDimitry Andric IOCSRWR_W, 109bdd1243dSDimitry Andric IOCSRWR_D, 110bdd1243dSDimitry Andric 111bdd1243dSDimitry Andric // Read CPU configuration information operation 112bdd1243dSDimitry Andric CPUCFG, 113bdd1243dSDimitry Andric // Intrinsic operations end ============================================= 11481ad6265SDimitry Andric }; 115972a253aSDimitry Andric } // end namespace LoongArchISD 11681ad6265SDimitry Andric 11781ad6265SDimitry Andric class LoongArchTargetLowering : public TargetLowering { 11881ad6265SDimitry Andric const LoongArchSubtarget &Subtarget; 11981ad6265SDimitry Andric 12081ad6265SDimitry Andric public: 12181ad6265SDimitry Andric explicit LoongArchTargetLowering(const TargetMachine &TM, 12281ad6265SDimitry Andric const LoongArchSubtarget &STI); 12381ad6265SDimitry Andric 12481ad6265SDimitry Andric const LoongArchSubtarget &getSubtarget() const { return Subtarget; } 12581ad6265SDimitry Andric 126bdd1243dSDimitry Andric bool isOffsetFoldingLegal(const GlobalAddressSDNode *GA) const override; 127bdd1243dSDimitry Andric 12881ad6265SDimitry Andric // Provide custom lowering hooks for some operations. 12981ad6265SDimitry Andric SDValue LowerOperation(SDValue Op, SelectionDAG &DAG) const override; 13081ad6265SDimitry Andric void ReplaceNodeResults(SDNode *N, SmallVectorImpl<SDValue> &Results, 13181ad6265SDimitry Andric SelectionDAG &DAG) const override; 13281ad6265SDimitry Andric 13381ad6265SDimitry Andric SDValue PerformDAGCombine(SDNode *N, DAGCombinerInfo &DCI) const override; 13481ad6265SDimitry Andric 13581ad6265SDimitry Andric // This method returns the name of a target specific DAG node. 13681ad6265SDimitry Andric const char *getTargetNodeName(unsigned Opcode) const override; 13781ad6265SDimitry Andric 13881ad6265SDimitry Andric // Lower incoming arguments, copy physregs into vregs. 13981ad6265SDimitry Andric SDValue LowerFormalArguments(SDValue Chain, CallingConv::ID CallConv, 14081ad6265SDimitry Andric bool IsVarArg, 14181ad6265SDimitry Andric const SmallVectorImpl<ISD::InputArg> &Ins, 14281ad6265SDimitry Andric const SDLoc &DL, SelectionDAG &DAG, 14381ad6265SDimitry Andric SmallVectorImpl<SDValue> &InVals) const override; 14481ad6265SDimitry Andric bool CanLowerReturn(CallingConv::ID CallConv, MachineFunction &MF, 14581ad6265SDimitry Andric bool IsVarArg, 14681ad6265SDimitry Andric const SmallVectorImpl<ISD::OutputArg> &Outs, 14781ad6265SDimitry Andric LLVMContext &Context) const override; 14881ad6265SDimitry Andric SDValue LowerReturn(SDValue Chain, CallingConv::ID CallConv, bool IsVarArg, 14981ad6265SDimitry Andric const SmallVectorImpl<ISD::OutputArg> &Outs, 15081ad6265SDimitry Andric const SmallVectorImpl<SDValue> &OutVals, const SDLoc &DL, 15181ad6265SDimitry Andric SelectionDAG &DAG) const override; 152753f127fSDimitry Andric SDValue LowerCall(TargetLowering::CallLoweringInfo &CLI, 153753f127fSDimitry Andric SmallVectorImpl<SDValue> &InVals) const override; 154bdd1243dSDimitry Andric bool isCheapToSpeculateCttz(Type *Ty) const override; 155bdd1243dSDimitry Andric bool isCheapToSpeculateCtlz(Type *Ty) const override; 156bdd1243dSDimitry Andric bool hasAndNot(SDValue Y) const override; 157bdd1243dSDimitry Andric TargetLowering::AtomicExpansionKind 158bdd1243dSDimitry Andric shouldExpandAtomicRMWInIR(AtomicRMWInst *AI) const override; 159bdd1243dSDimitry Andric 160bdd1243dSDimitry Andric Value *emitMaskedAtomicRMWIntrinsic(IRBuilderBase &Builder, AtomicRMWInst *AI, 161bdd1243dSDimitry Andric Value *AlignedAddr, Value *Incr, 162bdd1243dSDimitry Andric Value *Mask, Value *ShiftAmt, 163bdd1243dSDimitry Andric AtomicOrdering Ord) const override; 164bdd1243dSDimitry Andric 165bdd1243dSDimitry Andric EVT getSetCCResultType(const DataLayout &DL, LLVMContext &Context, 166bdd1243dSDimitry Andric EVT VT) const override; 167bdd1243dSDimitry Andric TargetLowering::AtomicExpansionKind 168bdd1243dSDimitry Andric shouldExpandAtomicCmpXchgInIR(AtomicCmpXchgInst *CI) const override; 169bdd1243dSDimitry Andric Value *emitMaskedAtomicCmpXchgIntrinsic(IRBuilderBase &Builder, 170bdd1243dSDimitry Andric AtomicCmpXchgInst *CI, 171bdd1243dSDimitry Andric Value *AlignedAddr, Value *CmpVal, 172bdd1243dSDimitry Andric Value *NewVal, Value *Mask, 173bdd1243dSDimitry Andric AtomicOrdering Ord) const override; 174bdd1243dSDimitry Andric 175bdd1243dSDimitry Andric bool getTgtMemIntrinsic(IntrinsicInfo &Info, const CallInst &I, 176bdd1243dSDimitry Andric MachineFunction &MF, 177bdd1243dSDimitry Andric unsigned Intrinsic) const override; 178bdd1243dSDimitry Andric 179bdd1243dSDimitry Andric bool isFMAFasterThanFMulAndFAdd(const MachineFunction &MF, 180bdd1243dSDimitry Andric EVT VT) const override; 181bdd1243dSDimitry Andric 182bdd1243dSDimitry Andric Register 183bdd1243dSDimitry Andric getExceptionPointerRegister(const Constant *PersonalityFn) const override; 184bdd1243dSDimitry Andric 185bdd1243dSDimitry Andric Register 186bdd1243dSDimitry Andric getExceptionSelectorRegister(const Constant *PersonalityFn) const override; 187bdd1243dSDimitry Andric 188bdd1243dSDimitry Andric ISD::NodeType getExtendForAtomicOps() const override { 189bdd1243dSDimitry Andric return ISD::SIGN_EXTEND; 190bdd1243dSDimitry Andric } 191bdd1243dSDimitry Andric 192bdd1243dSDimitry Andric Register getRegisterByName(const char *RegName, LLT VT, 193bdd1243dSDimitry Andric const MachineFunction &MF) const override; 194bdd1243dSDimitry Andric bool mayBeEmittedAsTailCall(const CallInst *CI) const override; 195bdd1243dSDimitry Andric 196bdd1243dSDimitry Andric bool decomposeMulByConstant(LLVMContext &Context, EVT VT, 197bdd1243dSDimitry Andric SDValue C) const override; 19881ad6265SDimitry Andric 199*06c3fb27SDimitry Andric bool isUsedByReturnOnly(SDNode *N, SDValue &Chain) const override; 200*06c3fb27SDimitry Andric 201*06c3fb27SDimitry Andric bool isLegalAddressingMode(const DataLayout &DL, const AddrMode &AM, Type *Ty, 202*06c3fb27SDimitry Andric unsigned AS, 203*06c3fb27SDimitry Andric Instruction *I = nullptr) const override; 204*06c3fb27SDimitry Andric 205*06c3fb27SDimitry Andric bool isLegalICmpImmediate(int64_t Imm) const override; 206*06c3fb27SDimitry Andric bool isLegalAddImmediate(int64_t Imm) const override; 207*06c3fb27SDimitry Andric bool isZExtFree(SDValue Val, EVT VT2) const override; 208*06c3fb27SDimitry Andric bool isSExtCheaperThanZExt(EVT SrcVT, EVT DstVT) const override; 209*06c3fb27SDimitry Andric 210*06c3fb27SDimitry Andric bool hasAndNotCompare(SDValue Y) const override; 211*06c3fb27SDimitry Andric 212*06c3fb27SDimitry Andric bool convertSelectOfConstantsToMath(EVT VT) const override { return true; } 213*06c3fb27SDimitry Andric 214*06c3fb27SDimitry Andric bool allowsMisalignedMemoryAccesses( 215*06c3fb27SDimitry Andric EVT VT, unsigned AddrSpace = 0, Align Alignment = Align(1), 216*06c3fb27SDimitry Andric MachineMemOperand::Flags Flags = MachineMemOperand::MONone, 217*06c3fb27SDimitry Andric unsigned *Fast = nullptr) const override; 218*06c3fb27SDimitry Andric 21981ad6265SDimitry Andric private: 22081ad6265SDimitry Andric /// Target-specific function used to lower LoongArch calling conventions. 221bdd1243dSDimitry Andric typedef bool LoongArchCCAssignFn(const DataLayout &DL, LoongArchABI::ABI ABI, 222bdd1243dSDimitry Andric unsigned ValNo, MVT ValVT, 22381ad6265SDimitry Andric CCValAssign::LocInfo LocInfo, 224bdd1243dSDimitry Andric ISD::ArgFlagsTy ArgFlags, CCState &State, 225bdd1243dSDimitry Andric bool IsFixed, bool IsReg, Type *OrigTy); 22681ad6265SDimitry Andric 227bdd1243dSDimitry Andric void analyzeInputArgs(MachineFunction &MF, CCState &CCInfo, 228bdd1243dSDimitry Andric const SmallVectorImpl<ISD::InputArg> &Ins, bool IsRet, 22981ad6265SDimitry Andric LoongArchCCAssignFn Fn) const; 230bdd1243dSDimitry Andric void analyzeOutputArgs(MachineFunction &MF, CCState &CCInfo, 23181ad6265SDimitry Andric const SmallVectorImpl<ISD::OutputArg> &Outs, 232bdd1243dSDimitry Andric bool IsRet, CallLoweringInfo *CLI, 23381ad6265SDimitry Andric LoongArchCCAssignFn Fn) const; 23481ad6265SDimitry Andric 235bdd1243dSDimitry Andric template <class NodeTy> 236bdd1243dSDimitry Andric SDValue getAddr(NodeTy *N, SelectionDAG &DAG, bool IsLocal = true) const; 237bdd1243dSDimitry Andric SDValue getStaticTLSAddr(GlobalAddressSDNode *N, SelectionDAG &DAG, 238*06c3fb27SDimitry Andric unsigned Opc, bool Large = false) const; 239bdd1243dSDimitry Andric SDValue getDynamicTLSAddr(GlobalAddressSDNode *N, SelectionDAG &DAG, 240*06c3fb27SDimitry Andric unsigned Opc, bool Large = false) const; 241753f127fSDimitry Andric SDValue lowerGlobalAddress(SDValue Op, SelectionDAG &DAG) const; 242bdd1243dSDimitry Andric SDValue lowerBlockAddress(SDValue Op, SelectionDAG &DAG) const; 243bdd1243dSDimitry Andric SDValue lowerJumpTable(SDValue Op, SelectionDAG &DAG) const; 244bdd1243dSDimitry Andric SDValue lowerGlobalTLSAddress(SDValue Op, SelectionDAG &DAG) const; 24581ad6265SDimitry Andric SDValue lowerShiftLeftParts(SDValue Op, SelectionDAG &DAG) const; 24681ad6265SDimitry Andric SDValue lowerShiftRightParts(SDValue Op, SelectionDAG &DAG, bool IsSRA) const; 247753f127fSDimitry Andric 248753f127fSDimitry Andric MachineBasicBlock * 249753f127fSDimitry Andric EmitInstrWithCustomInserter(MachineInstr &MI, 250753f127fSDimitry Andric MachineBasicBlock *BB) const override; 251753f127fSDimitry Andric SDValue lowerConstantPool(SDValue Op, SelectionDAG &DAG) const; 252bdd1243dSDimitry Andric SDValue lowerEH_DWARF_CFA(SDValue Op, SelectionDAG &DAG) const; 253753f127fSDimitry Andric SDValue lowerFP_TO_SINT(SDValue Op, SelectionDAG &DAG) const; 254753f127fSDimitry Andric SDValue lowerBITCAST(SDValue Op, SelectionDAG &DAG) const; 255753f127fSDimitry Andric SDValue lowerUINT_TO_FP(SDValue Op, SelectionDAG &DAG) const; 256bdd1243dSDimitry Andric SDValue lowerSINT_TO_FP(SDValue Op, SelectionDAG &DAG) const; 257bdd1243dSDimitry Andric SDValue lowerVASTART(SDValue Op, SelectionDAG &DAG) const; 258bdd1243dSDimitry Andric SDValue lowerINTRINSIC_WO_CHAIN(SDValue Op, SelectionDAG &DAG) const; 259bdd1243dSDimitry Andric SDValue lowerINTRINSIC_W_CHAIN(SDValue Op, SelectionDAG &DAG) const; 260bdd1243dSDimitry Andric SDValue lowerINTRINSIC_VOID(SDValue Op, SelectionDAG &DAG) const; 261bdd1243dSDimitry Andric SDValue lowerFRAMEADDR(SDValue Op, SelectionDAG &DAG) const; 262bdd1243dSDimitry Andric SDValue lowerRETURNADDR(SDValue Op, SelectionDAG &DAG) const; 263bdd1243dSDimitry Andric SDValue lowerWRITE_REGISTER(SDValue Op, SelectionDAG &DAG) const; 264753f127fSDimitry Andric 265753f127fSDimitry Andric bool isFPImmLegal(const APFloat &Imm, EVT VT, 266753f127fSDimitry Andric bool ForCodeSize) const override; 267753f127fSDimitry Andric 268bdd1243dSDimitry Andric bool shouldInsertFencesForAtomic(const Instruction *I) const override; 269bdd1243dSDimitry Andric 270bdd1243dSDimitry Andric ConstraintType getConstraintType(StringRef Constraint) const override; 271bdd1243dSDimitry Andric 272bdd1243dSDimitry Andric unsigned getInlineAsmMemConstraint(StringRef ConstraintCode) const override; 273bdd1243dSDimitry Andric 274bdd1243dSDimitry Andric std::pair<unsigned, const TargetRegisterClass *> 275bdd1243dSDimitry Andric getRegForInlineAsmConstraint(const TargetRegisterInfo *TRI, 276bdd1243dSDimitry Andric StringRef Constraint, MVT VT) const override; 277bdd1243dSDimitry Andric 278bdd1243dSDimitry Andric void LowerAsmOperandForConstraint(SDValue Op, std::string &Constraint, 279bdd1243dSDimitry Andric std::vector<SDValue> &Ops, 280bdd1243dSDimitry Andric SelectionDAG &DAG) const override; 281bdd1243dSDimitry Andric 282bdd1243dSDimitry Andric bool isEligibleForTailCallOptimization( 283bdd1243dSDimitry Andric CCState &CCInfo, CallLoweringInfo &CLI, MachineFunction &MF, 284bdd1243dSDimitry Andric const SmallVectorImpl<CCValAssign> &ArgLocs) const; 28581ad6265SDimitry Andric }; 28681ad6265SDimitry Andric 28781ad6265SDimitry Andric } // end namespace llvm 28881ad6265SDimitry Andric 28981ad6265SDimitry Andric #endif // LLVM_LIB_TARGET_LOONGARCH_LOONGARCHISELLOWERING_H 290