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, 32*bdd1243dSDimitry Andric TAIL, 33*bdd1243dSDimitry 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 40*bdd1243dSDimitry Andric ROTL_W, 41*bdd1243dSDimitry Andric ROTR_W, 42*bdd1243dSDimitry Andric 43753f127fSDimitry Andric // FPR<->GPR transfer operations 44753f127fSDimitry Andric MOVGR2FR_W_LA64, 45753f127fSDimitry Andric MOVFR2GR_S_LA64, 46*bdd1243dSDimitry Andric MOVFCSR2GR, 47*bdd1243dSDimitry Andric MOVGR2FCSR, 48753f127fSDimitry Andric 49753f127fSDimitry Andric FTINT, 50753f127fSDimitry Andric 51*bdd1243dSDimitry Andric // Bit counting operations 52*bdd1243dSDimitry Andric CLZ_W, 53*bdd1243dSDimitry Andric CTZ_W, 54*bdd1243dSDimitry Andric 55753f127fSDimitry Andric BSTRINS, 5681ad6265SDimitry Andric BSTRPICK, 5781ad6265SDimitry Andric 58*bdd1243dSDimitry Andric // Byte-swapping and bit-reversal 59*bdd1243dSDimitry Andric REVB_2H, 60*bdd1243dSDimitry Andric REVB_2W, 61*bdd1243dSDimitry Andric BITREV_4B, 62*bdd1243dSDimitry Andric BITREV_W, 63*bdd1243dSDimitry Andric 64*bdd1243dSDimitry Andric // Intrinsic operations start ============================================ 65*bdd1243dSDimitry Andric BREAK, 66*bdd1243dSDimitry Andric CACOP_D, 67*bdd1243dSDimitry Andric CACOP_W, 68*bdd1243dSDimitry Andric DBAR, 69*bdd1243dSDimitry Andric IBAR, 70*bdd1243dSDimitry Andric SYSCALL, 71*bdd1243dSDimitry Andric 72*bdd1243dSDimitry Andric // CRC check operations 73*bdd1243dSDimitry Andric CRC_W_B_W, 74*bdd1243dSDimitry Andric CRC_W_H_W, 75*bdd1243dSDimitry Andric CRC_W_W_W, 76*bdd1243dSDimitry Andric CRC_W_D_W, 77*bdd1243dSDimitry Andric CRCC_W_B_W, 78*bdd1243dSDimitry Andric CRCC_W_H_W, 79*bdd1243dSDimitry Andric CRCC_W_W_W, 80*bdd1243dSDimitry Andric CRCC_W_D_W, 81*bdd1243dSDimitry Andric 82*bdd1243dSDimitry Andric CSRRD, 83*bdd1243dSDimitry Andric CSRWR, 84*bdd1243dSDimitry Andric CSRXCHG, 85*bdd1243dSDimitry Andric 86*bdd1243dSDimitry Andric // IOCSR access operations 87*bdd1243dSDimitry Andric IOCSRRD_B, 88*bdd1243dSDimitry Andric IOCSRRD_W, 89*bdd1243dSDimitry Andric IOCSRRD_H, 90*bdd1243dSDimitry Andric IOCSRRD_D, 91*bdd1243dSDimitry Andric IOCSRWR_B, 92*bdd1243dSDimitry Andric IOCSRWR_H, 93*bdd1243dSDimitry Andric IOCSRWR_W, 94*bdd1243dSDimitry Andric IOCSRWR_D, 95*bdd1243dSDimitry Andric 96*bdd1243dSDimitry Andric // Read CPU configuration information operation 97*bdd1243dSDimitry Andric CPUCFG, 98*bdd1243dSDimitry Andric // Intrinsic operations end ============================================= 9981ad6265SDimitry Andric }; 100972a253aSDimitry Andric } // end namespace LoongArchISD 10181ad6265SDimitry Andric 10281ad6265SDimitry Andric class LoongArchTargetLowering : public TargetLowering { 10381ad6265SDimitry Andric const LoongArchSubtarget &Subtarget; 10481ad6265SDimitry Andric 10581ad6265SDimitry Andric public: 10681ad6265SDimitry Andric explicit LoongArchTargetLowering(const TargetMachine &TM, 10781ad6265SDimitry Andric const LoongArchSubtarget &STI); 10881ad6265SDimitry Andric 10981ad6265SDimitry Andric const LoongArchSubtarget &getSubtarget() const { return Subtarget; } 11081ad6265SDimitry Andric 111*bdd1243dSDimitry Andric bool isOffsetFoldingLegal(const GlobalAddressSDNode *GA) const override; 112*bdd1243dSDimitry Andric 11381ad6265SDimitry Andric // Provide custom lowering hooks for some operations. 11481ad6265SDimitry Andric SDValue LowerOperation(SDValue Op, SelectionDAG &DAG) const override; 11581ad6265SDimitry Andric void ReplaceNodeResults(SDNode *N, SmallVectorImpl<SDValue> &Results, 11681ad6265SDimitry Andric SelectionDAG &DAG) const override; 11781ad6265SDimitry Andric 11881ad6265SDimitry Andric SDValue PerformDAGCombine(SDNode *N, DAGCombinerInfo &DCI) const override; 11981ad6265SDimitry Andric 12081ad6265SDimitry Andric // This method returns the name of a target specific DAG node. 12181ad6265SDimitry Andric const char *getTargetNodeName(unsigned Opcode) const override; 12281ad6265SDimitry Andric 12381ad6265SDimitry Andric // Lower incoming arguments, copy physregs into vregs. 12481ad6265SDimitry Andric SDValue LowerFormalArguments(SDValue Chain, CallingConv::ID CallConv, 12581ad6265SDimitry Andric bool IsVarArg, 12681ad6265SDimitry Andric const SmallVectorImpl<ISD::InputArg> &Ins, 12781ad6265SDimitry Andric const SDLoc &DL, SelectionDAG &DAG, 12881ad6265SDimitry Andric SmallVectorImpl<SDValue> &InVals) const override; 12981ad6265SDimitry Andric bool CanLowerReturn(CallingConv::ID CallConv, MachineFunction &MF, 13081ad6265SDimitry Andric bool IsVarArg, 13181ad6265SDimitry Andric const SmallVectorImpl<ISD::OutputArg> &Outs, 13281ad6265SDimitry Andric LLVMContext &Context) const override; 13381ad6265SDimitry Andric SDValue LowerReturn(SDValue Chain, CallingConv::ID CallConv, bool IsVarArg, 13481ad6265SDimitry Andric const SmallVectorImpl<ISD::OutputArg> &Outs, 13581ad6265SDimitry Andric const SmallVectorImpl<SDValue> &OutVals, const SDLoc &DL, 13681ad6265SDimitry Andric SelectionDAG &DAG) const override; 137753f127fSDimitry Andric SDValue LowerCall(TargetLowering::CallLoweringInfo &CLI, 138753f127fSDimitry Andric SmallVectorImpl<SDValue> &InVals) const override; 139*bdd1243dSDimitry Andric bool isCheapToSpeculateCttz(Type *Ty) const override; 140*bdd1243dSDimitry Andric bool isCheapToSpeculateCtlz(Type *Ty) const override; 141*bdd1243dSDimitry Andric bool hasAndNot(SDValue Y) const override; 142*bdd1243dSDimitry Andric TargetLowering::AtomicExpansionKind 143*bdd1243dSDimitry Andric shouldExpandAtomicRMWInIR(AtomicRMWInst *AI) const override; 144*bdd1243dSDimitry Andric 145*bdd1243dSDimitry Andric Value *emitMaskedAtomicRMWIntrinsic(IRBuilderBase &Builder, AtomicRMWInst *AI, 146*bdd1243dSDimitry Andric Value *AlignedAddr, Value *Incr, 147*bdd1243dSDimitry Andric Value *Mask, Value *ShiftAmt, 148*bdd1243dSDimitry Andric AtomicOrdering Ord) const override; 149*bdd1243dSDimitry Andric 150*bdd1243dSDimitry Andric EVT getSetCCResultType(const DataLayout &DL, LLVMContext &Context, 151*bdd1243dSDimitry Andric EVT VT) const override; 152*bdd1243dSDimitry Andric TargetLowering::AtomicExpansionKind 153*bdd1243dSDimitry Andric shouldExpandAtomicCmpXchgInIR(AtomicCmpXchgInst *CI) const override; 154*bdd1243dSDimitry Andric Value *emitMaskedAtomicCmpXchgIntrinsic(IRBuilderBase &Builder, 155*bdd1243dSDimitry Andric AtomicCmpXchgInst *CI, 156*bdd1243dSDimitry Andric Value *AlignedAddr, Value *CmpVal, 157*bdd1243dSDimitry Andric Value *NewVal, Value *Mask, 158*bdd1243dSDimitry Andric AtomicOrdering Ord) const override; 159*bdd1243dSDimitry Andric 160*bdd1243dSDimitry Andric bool getTgtMemIntrinsic(IntrinsicInfo &Info, const CallInst &I, 161*bdd1243dSDimitry Andric MachineFunction &MF, 162*bdd1243dSDimitry Andric unsigned Intrinsic) const override; 163*bdd1243dSDimitry Andric 164*bdd1243dSDimitry Andric bool isFMAFasterThanFMulAndFAdd(const MachineFunction &MF, 165*bdd1243dSDimitry Andric EVT VT) const override; 166*bdd1243dSDimitry Andric 167*bdd1243dSDimitry Andric Register 168*bdd1243dSDimitry Andric getExceptionPointerRegister(const Constant *PersonalityFn) const override; 169*bdd1243dSDimitry Andric 170*bdd1243dSDimitry Andric Register 171*bdd1243dSDimitry Andric getExceptionSelectorRegister(const Constant *PersonalityFn) const override; 172*bdd1243dSDimitry Andric 173*bdd1243dSDimitry Andric ISD::NodeType getExtendForAtomicOps() const override { 174*bdd1243dSDimitry Andric return ISD::SIGN_EXTEND; 175*bdd1243dSDimitry Andric } 176*bdd1243dSDimitry Andric 177*bdd1243dSDimitry Andric Register getRegisterByName(const char *RegName, LLT VT, 178*bdd1243dSDimitry Andric const MachineFunction &MF) const override; 179*bdd1243dSDimitry Andric bool mayBeEmittedAsTailCall(const CallInst *CI) const override; 180*bdd1243dSDimitry Andric 181*bdd1243dSDimitry Andric bool decomposeMulByConstant(LLVMContext &Context, EVT VT, 182*bdd1243dSDimitry Andric SDValue C) const override; 18381ad6265SDimitry Andric 18481ad6265SDimitry Andric private: 18581ad6265SDimitry Andric /// Target-specific function used to lower LoongArch calling conventions. 186*bdd1243dSDimitry Andric typedef bool LoongArchCCAssignFn(const DataLayout &DL, LoongArchABI::ABI ABI, 187*bdd1243dSDimitry Andric unsigned ValNo, MVT ValVT, 18881ad6265SDimitry Andric CCValAssign::LocInfo LocInfo, 189*bdd1243dSDimitry Andric ISD::ArgFlagsTy ArgFlags, CCState &State, 190*bdd1243dSDimitry Andric bool IsFixed, bool IsReg, Type *OrigTy); 19181ad6265SDimitry Andric 192*bdd1243dSDimitry Andric void analyzeInputArgs(MachineFunction &MF, CCState &CCInfo, 193*bdd1243dSDimitry Andric const SmallVectorImpl<ISD::InputArg> &Ins, bool IsRet, 19481ad6265SDimitry Andric LoongArchCCAssignFn Fn) const; 195*bdd1243dSDimitry Andric void analyzeOutputArgs(MachineFunction &MF, CCState &CCInfo, 19681ad6265SDimitry Andric const SmallVectorImpl<ISD::OutputArg> &Outs, 197*bdd1243dSDimitry Andric bool IsRet, CallLoweringInfo *CLI, 19881ad6265SDimitry Andric LoongArchCCAssignFn Fn) const; 19981ad6265SDimitry Andric 200*bdd1243dSDimitry Andric template <class NodeTy> 201*bdd1243dSDimitry Andric SDValue getAddr(NodeTy *N, SelectionDAG &DAG, bool IsLocal = true) const; 202*bdd1243dSDimitry Andric SDValue getStaticTLSAddr(GlobalAddressSDNode *N, SelectionDAG &DAG, 203*bdd1243dSDimitry Andric unsigned Opc) const; 204*bdd1243dSDimitry Andric SDValue getDynamicTLSAddr(GlobalAddressSDNode *N, SelectionDAG &DAG, 205*bdd1243dSDimitry Andric unsigned Opc) const; 206753f127fSDimitry Andric SDValue lowerGlobalAddress(SDValue Op, SelectionDAG &DAG) const; 207*bdd1243dSDimitry Andric SDValue lowerBlockAddress(SDValue Op, SelectionDAG &DAG) const; 208*bdd1243dSDimitry Andric SDValue lowerJumpTable(SDValue Op, SelectionDAG &DAG) const; 209*bdd1243dSDimitry Andric SDValue lowerGlobalTLSAddress(SDValue Op, SelectionDAG &DAG) const; 21081ad6265SDimitry Andric SDValue lowerShiftLeftParts(SDValue Op, SelectionDAG &DAG) const; 21181ad6265SDimitry Andric SDValue lowerShiftRightParts(SDValue Op, SelectionDAG &DAG, bool IsSRA) const; 212753f127fSDimitry Andric 213753f127fSDimitry Andric MachineBasicBlock * 214753f127fSDimitry Andric EmitInstrWithCustomInserter(MachineInstr &MI, 215753f127fSDimitry Andric MachineBasicBlock *BB) const override; 216753f127fSDimitry Andric SDValue lowerConstantPool(SDValue Op, SelectionDAG &DAG) const; 217*bdd1243dSDimitry Andric SDValue lowerEH_DWARF_CFA(SDValue Op, SelectionDAG &DAG) const; 218753f127fSDimitry Andric SDValue lowerFP_TO_SINT(SDValue Op, SelectionDAG &DAG) const; 219753f127fSDimitry Andric SDValue lowerBITCAST(SDValue Op, SelectionDAG &DAG) const; 220753f127fSDimitry Andric SDValue lowerUINT_TO_FP(SDValue Op, SelectionDAG &DAG) const; 221*bdd1243dSDimitry Andric SDValue lowerSINT_TO_FP(SDValue Op, SelectionDAG &DAG) const; 222*bdd1243dSDimitry Andric SDValue lowerVASTART(SDValue Op, SelectionDAG &DAG) const; 223*bdd1243dSDimitry Andric SDValue lowerINTRINSIC_WO_CHAIN(SDValue Op, SelectionDAG &DAG) const; 224*bdd1243dSDimitry Andric SDValue lowerINTRINSIC_W_CHAIN(SDValue Op, SelectionDAG &DAG) const; 225*bdd1243dSDimitry Andric SDValue lowerINTRINSIC_VOID(SDValue Op, SelectionDAG &DAG) const; 226*bdd1243dSDimitry Andric SDValue lowerFRAMEADDR(SDValue Op, SelectionDAG &DAG) const; 227*bdd1243dSDimitry Andric SDValue lowerRETURNADDR(SDValue Op, SelectionDAG &DAG) const; 228*bdd1243dSDimitry Andric SDValue lowerWRITE_REGISTER(SDValue Op, SelectionDAG &DAG) const; 229753f127fSDimitry Andric 230753f127fSDimitry Andric bool isFPImmLegal(const APFloat &Imm, EVT VT, 231753f127fSDimitry Andric bool ForCodeSize) const override; 232753f127fSDimitry Andric 233*bdd1243dSDimitry Andric bool shouldInsertFencesForAtomic(const Instruction *I) const override; 234*bdd1243dSDimitry Andric 235*bdd1243dSDimitry Andric ConstraintType getConstraintType(StringRef Constraint) const override; 236*bdd1243dSDimitry Andric 237*bdd1243dSDimitry Andric unsigned getInlineAsmMemConstraint(StringRef ConstraintCode) const override; 238*bdd1243dSDimitry Andric 239*bdd1243dSDimitry Andric std::pair<unsigned, const TargetRegisterClass *> 240*bdd1243dSDimitry Andric getRegForInlineAsmConstraint(const TargetRegisterInfo *TRI, 241*bdd1243dSDimitry Andric StringRef Constraint, MVT VT) const override; 242*bdd1243dSDimitry Andric 243*bdd1243dSDimitry Andric void LowerAsmOperandForConstraint(SDValue Op, std::string &Constraint, 244*bdd1243dSDimitry Andric std::vector<SDValue> &Ops, 245*bdd1243dSDimitry Andric SelectionDAG &DAG) const override; 246*bdd1243dSDimitry Andric 247*bdd1243dSDimitry Andric bool isEligibleForTailCallOptimization( 248*bdd1243dSDimitry Andric CCState &CCInfo, CallLoweringInfo &CLI, MachineFunction &MF, 249*bdd1243dSDimitry Andric const SmallVectorImpl<CCValAssign> &ArgLocs) const; 25081ad6265SDimitry Andric }; 25181ad6265SDimitry Andric 25281ad6265SDimitry Andric } // end namespace llvm 25381ad6265SDimitry Andric 25481ad6265SDimitry Andric #endif // LLVM_LIB_TARGET_LOONGARCH_LOONGARCHISELLOWERING_H 255