1 //=- LoongArchISelLowering.h - LoongArch DAG Lowering Interface -*- C++ -*-===// 2 // 3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 4 // See https://llvm.org/LICENSE.txt for license information. 5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 6 // 7 //===----------------------------------------------------------------------===// 8 // 9 // This file defines the interfaces that LoongArch uses to lower LLVM code into 10 // a selection DAG. 11 // 12 //===----------------------------------------------------------------------===// 13 14 #ifndef LLVM_LIB_TARGET_LOONGARCH_LOONGARCHISELLOWERING_H 15 #define LLVM_LIB_TARGET_LOONGARCH_LOONGARCHISELLOWERING_H 16 17 #include "LoongArch.h" 18 #include "llvm/CodeGen/CallingConvLower.h" 19 #include "llvm/CodeGen/SelectionDAG.h" 20 #include "llvm/CodeGen/TargetLowering.h" 21 22 namespace llvm { 23 class LoongArchSubtarget; 24 namespace LoongArchISD { 25 enum NodeType : unsigned { 26 FIRST_NUMBER = ISD::BUILTIN_OP_END, 27 28 // TODO: add more LoongArchISDs 29 CALL, 30 CALL_MEDIUM, 31 CALL_LARGE, 32 RET, 33 TAIL, 34 TAIL_MEDIUM, 35 TAIL_LARGE, 36 37 // Select 38 SELECT_CC, 39 40 // 32-bit shifts, directly matching the semantics of the named LoongArch 41 // instructions. 42 SLL_W, 43 SRA_W, 44 SRL_W, 45 46 ROTL_W, 47 ROTR_W, 48 49 // unsigned 32-bit integer division 50 DIV_W, 51 MOD_W, 52 DIV_WU, 53 MOD_WU, 54 55 // FPR<->GPR transfer operations 56 MOVGR2FR_W_LA64, 57 MOVFR2GR_S_LA64, 58 MOVFCSR2GR, 59 MOVGR2FCSR, 60 61 FTINT, 62 63 // Build and split F64 pair 64 BUILD_PAIR_F64, 65 SPLIT_PAIR_F64, 66 67 // Bit counting operations 68 CLZ_W, 69 CTZ_W, 70 71 BSTRINS, 72 BSTRPICK, 73 74 // Byte-swapping and bit-reversal 75 REVB_2H, 76 REVB_2W, 77 BITREV_4B, 78 BITREV_8B, 79 BITREV_W, 80 81 // Intrinsic operations start ============================================ 82 BREAK, 83 CACOP_D, 84 CACOP_W, 85 DBAR, 86 IBAR, 87 SYSCALL, 88 89 // CRC check operations 90 CRC_W_B_W, 91 CRC_W_H_W, 92 CRC_W_W_W, 93 CRC_W_D_W, 94 CRCC_W_B_W, 95 CRCC_W_H_W, 96 CRCC_W_W_W, 97 CRCC_W_D_W, 98 99 CSRRD, 100 101 // Write new value to CSR and return old value. 102 // Operand 0: A chain pointer. 103 // Operand 1: The new value to write. 104 // Operand 2: The address of the required CSR. 105 // Result 0: The old value of the CSR. 106 // Result 1: The new chain pointer. 107 CSRWR, 108 109 // Similar to CSRWR but with a write mask. 110 // Operand 0: A chain pointer. 111 // Operand 1: The new value to write. 112 // Operand 2: The write mask. 113 // Operand 3: The address of the required CSR. 114 // Result 0: The old value of the CSR. 115 // Result 1: The new chain pointer. 116 CSRXCHG, 117 118 // IOCSR access operations 119 IOCSRRD_B, 120 IOCSRRD_W, 121 IOCSRRD_H, 122 IOCSRRD_D, 123 IOCSRWR_B, 124 IOCSRWR_H, 125 IOCSRWR_W, 126 IOCSRWR_D, 127 128 // Read CPU configuration information operation 129 CPUCFG, 130 131 // Vector Shuffle 132 VREPLVE, 133 VSHUF, 134 VPICKEV, 135 VPICKOD, 136 VPACKEV, 137 VPACKOD, 138 VILVL, 139 VILVH, 140 VSHUF4I, 141 VREPLVEI, 142 VREPLGR2VR, 143 XVPERMI, 144 145 // Extended vector element extraction 146 VPICK_SEXT_ELT, 147 VPICK_ZEXT_ELT, 148 149 // Vector comparisons 150 VALL_ZERO, 151 VANY_ZERO, 152 VALL_NONZERO, 153 VANY_NONZERO, 154 155 // Floating point approximate reciprocal operation 156 FRECIPE, 157 FRSQRTE, 158 159 // Vector logicial left / right shift by immediate 160 VSLLI, 161 VSRLI, 162 163 // Vector byte logicial left / right shift 164 VBSLL, 165 VBSRL, 166 167 // Scalar load broadcast to vector 168 VLDREPL, 169 170 // Vector mask set by condition 171 VMSKLTZ, 172 VMSKGEZ, 173 VMSKEQZ, 174 VMSKNEZ, 175 XVMSKLTZ, 176 XVMSKGEZ, 177 XVMSKEQZ, 178 XVMSKNEZ, 179 180 // Intrinsic operations end ============================================= 181 }; 182 } // end namespace LoongArchISD 183 184 class LoongArchTargetLowering : public TargetLowering { 185 const LoongArchSubtarget &Subtarget; 186 187 public: 188 explicit LoongArchTargetLowering(const TargetMachine &TM, 189 const LoongArchSubtarget &STI); 190 getSubtarget()191 const LoongArchSubtarget &getSubtarget() const { return Subtarget; } 192 193 bool isOffsetFoldingLegal(const GlobalAddressSDNode *GA) const override; 194 195 // Provide custom lowering hooks for some operations. 196 SDValue LowerOperation(SDValue Op, SelectionDAG &DAG) const override; 197 void ReplaceNodeResults(SDNode *N, SmallVectorImpl<SDValue> &Results, 198 SelectionDAG &DAG) const override; 199 200 SDValue PerformDAGCombine(SDNode *N, DAGCombinerInfo &DCI) const override; 201 202 // This method returns the name of a target specific DAG node. 203 const char *getTargetNodeName(unsigned Opcode) const override; 204 205 // Lower incoming arguments, copy physregs into vregs. 206 SDValue LowerFormalArguments(SDValue Chain, CallingConv::ID CallConv, 207 bool IsVarArg, 208 const SmallVectorImpl<ISD::InputArg> &Ins, 209 const SDLoc &DL, SelectionDAG &DAG, 210 SmallVectorImpl<SDValue> &InVals) const override; 211 bool CanLowerReturn(CallingConv::ID CallConv, MachineFunction &MF, 212 bool IsVarArg, 213 const SmallVectorImpl<ISD::OutputArg> &Outs, 214 LLVMContext &Context, const Type *RetTy) const override; 215 SDValue LowerReturn(SDValue Chain, CallingConv::ID CallConv, bool IsVarArg, 216 const SmallVectorImpl<ISD::OutputArg> &Outs, 217 const SmallVectorImpl<SDValue> &OutVals, const SDLoc &DL, 218 SelectionDAG &DAG) const override; 219 SDValue LowerCall(TargetLowering::CallLoweringInfo &CLI, 220 SmallVectorImpl<SDValue> &InVals) const override; 221 bool isCheapToSpeculateCttz(Type *Ty) const override; 222 bool isCheapToSpeculateCtlz(Type *Ty) const override; 223 bool hasAndNot(SDValue Y) const override; 224 TargetLowering::AtomicExpansionKind 225 shouldExpandAtomicRMWInIR(AtomicRMWInst *AI) const override; 226 void emitExpandAtomicRMW(AtomicRMWInst *AI) const override; 227 228 Value *emitMaskedAtomicRMWIntrinsic(IRBuilderBase &Builder, AtomicRMWInst *AI, 229 Value *AlignedAddr, Value *Incr, 230 Value *Mask, Value *ShiftAmt, 231 AtomicOrdering Ord) const override; 232 233 EVT getSetCCResultType(const DataLayout &DL, LLVMContext &Context, 234 EVT VT) const override; 235 TargetLowering::AtomicExpansionKind 236 shouldExpandAtomicCmpXchgInIR(AtomicCmpXchgInst *CI) const override; 237 Value *emitMaskedAtomicCmpXchgIntrinsic(IRBuilderBase &Builder, 238 AtomicCmpXchgInst *CI, 239 Value *AlignedAddr, Value *CmpVal, 240 Value *NewVal, Value *Mask, 241 AtomicOrdering Ord) const override; 242 243 bool getTgtMemIntrinsic(IntrinsicInfo &Info, const CallInst &I, 244 MachineFunction &MF, 245 unsigned Intrinsic) const override; 246 247 bool isFMAFasterThanFMulAndFAdd(const MachineFunction &MF, 248 EVT VT) const override; 249 250 Register 251 getExceptionPointerRegister(const Constant *PersonalityFn) const override; 252 253 Register 254 getExceptionSelectorRegister(const Constant *PersonalityFn) const override; 255 isFsqrtCheap(SDValue Operand,SelectionDAG & DAG)256 bool isFsqrtCheap(SDValue Operand, SelectionDAG &DAG) const override { 257 return true; 258 } 259 260 SDValue getSqrtEstimate(SDValue Operand, SelectionDAG &DAG, int Enabled, 261 int &RefinementSteps, bool &UseOneConstNR, 262 bool Reciprocal) const override; 263 264 SDValue getRecipEstimate(SDValue Operand, SelectionDAG &DAG, int Enabled, 265 int &RefinementSteps) const override; 266 getExtendForAtomicOps()267 ISD::NodeType getExtendForAtomicOps() const override { 268 return ISD::SIGN_EXTEND; 269 } 270 271 ISD::NodeType getExtendForAtomicCmpSwapArg() const override; 272 273 Register getRegisterByName(const char *RegName, LLT VT, 274 const MachineFunction &MF) const override; 275 bool mayBeEmittedAsTailCall(const CallInst *CI) const override; 276 277 bool decomposeMulByConstant(LLVMContext &Context, EVT VT, 278 SDValue C) const override; 279 280 bool isUsedByReturnOnly(SDNode *N, SDValue &Chain) const override; 281 282 bool isLegalAddressingMode(const DataLayout &DL, const AddrMode &AM, Type *Ty, 283 unsigned AS, 284 Instruction *I = nullptr) const override; 285 286 bool isLegalICmpImmediate(int64_t Imm) const override; 287 bool isLegalAddImmediate(int64_t Imm) const override; 288 bool isZExtFree(SDValue Val, EVT VT2) const override; 289 bool isSExtCheaperThanZExt(EVT SrcVT, EVT DstVT) const override; 290 bool signExtendConstant(const ConstantInt *CI) const override; 291 292 bool hasAndNotCompare(SDValue Y) const override; 293 convertSelectOfConstantsToMath(EVT VT)294 bool convertSelectOfConstantsToMath(EVT VT) const override { return true; } 295 296 bool allowsMisalignedMemoryAccesses( 297 EVT VT, unsigned AddrSpace = 0, Align Alignment = Align(1), 298 MachineMemOperand::Flags Flags = MachineMemOperand::MONone, 299 unsigned *Fast = nullptr) const override; 300 isShuffleMaskLegal(ArrayRef<int> Mask,EVT VT)301 bool isShuffleMaskLegal(ArrayRef<int> Mask, EVT VT) const override { 302 if (!VT.isSimple()) 303 return false; 304 305 // Not for i1 vectors 306 if (VT.getSimpleVT().getScalarType() == MVT::i1) 307 return false; 308 309 return isTypeLegal(VT.getSimpleVT()); 310 } shouldConsiderGEPOffsetSplit()311 bool shouldConsiderGEPOffsetSplit() const override { return true; } 312 bool shouldSignExtendTypeInLibCall(Type *Ty, bool IsSigned) const override; 313 bool shouldExtendTypeInLibCall(EVT Type) const override; 314 315 bool shouldAlignPointerArgs(CallInst *CI, unsigned &MinSize, 316 Align &PrefAlign) const override; 317 318 bool isFPImmVLDILegal(const APFloat &Imm, EVT VT) const; 319 LegalizeTypeAction getPreferredVectorAction(MVT VT) const override; 320 321 bool SimplifyDemandedBitsForTargetNode(SDValue Op, const APInt &DemandedBits, 322 const APInt &DemandedElts, 323 KnownBits &Known, 324 TargetLoweringOpt &TLO, 325 unsigned Depth) const override; 326 327 private: 328 /// Target-specific function used to lower LoongArch calling conventions. 329 typedef bool LoongArchCCAssignFn(const DataLayout &DL, LoongArchABI::ABI ABI, 330 unsigned ValNo, MVT ValVT, 331 CCValAssign::LocInfo LocInfo, 332 ISD::ArgFlagsTy ArgFlags, CCState &State, 333 bool IsFixed, bool IsRet, Type *OrigTy); 334 335 void analyzeInputArgs(MachineFunction &MF, CCState &CCInfo, 336 const SmallVectorImpl<ISD::InputArg> &Ins, bool IsRet, 337 LoongArchCCAssignFn Fn) const; 338 void analyzeOutputArgs(MachineFunction &MF, CCState &CCInfo, 339 const SmallVectorImpl<ISD::OutputArg> &Outs, 340 bool IsRet, CallLoweringInfo *CLI, 341 LoongArchCCAssignFn Fn) const; 342 343 template <class NodeTy> 344 SDValue getAddr(NodeTy *N, SelectionDAG &DAG, CodeModel::Model M, 345 bool IsLocal = true) const; 346 SDValue getStaticTLSAddr(GlobalAddressSDNode *N, SelectionDAG &DAG, 347 unsigned Opc, bool UseGOT, bool Large = false) const; 348 SDValue getDynamicTLSAddr(GlobalAddressSDNode *N, SelectionDAG &DAG, 349 unsigned Opc, bool Large = false) const; 350 SDValue getTLSDescAddr(GlobalAddressSDNode *N, SelectionDAG &DAG, 351 unsigned Opc, bool Large = false) const; 352 SDValue lowerGlobalAddress(SDValue Op, SelectionDAG &DAG) const; 353 SDValue lowerBlockAddress(SDValue Op, SelectionDAG &DAG) const; 354 SDValue lowerJumpTable(SDValue Op, SelectionDAG &DAG) const; 355 SDValue lowerGlobalTLSAddress(SDValue Op, SelectionDAG &DAG) const; 356 SDValue lowerShiftLeftParts(SDValue Op, SelectionDAG &DAG) const; 357 SDValue lowerShiftRightParts(SDValue Op, SelectionDAG &DAG, bool IsSRA) const; 358 359 MachineBasicBlock * 360 EmitInstrWithCustomInserter(MachineInstr &MI, 361 MachineBasicBlock *BB) const override; 362 SDValue lowerATOMIC_FENCE(SDValue Op, SelectionDAG &DAG) const; 363 SDValue lowerConstantPool(SDValue Op, SelectionDAG &DAG) const; 364 SDValue lowerEH_DWARF_CFA(SDValue Op, SelectionDAG &DAG) const; 365 SDValue lowerFP_TO_SINT(SDValue Op, SelectionDAG &DAG) const; 366 SDValue lowerBITCAST(SDValue Op, SelectionDAG &DAG) const; 367 SDValue lowerUINT_TO_FP(SDValue Op, SelectionDAG &DAG) const; 368 SDValue lowerSINT_TO_FP(SDValue Op, SelectionDAG &DAG) const; 369 SDValue lowerVASTART(SDValue Op, SelectionDAG &DAG) const; 370 SDValue lowerINTRINSIC_WO_CHAIN(SDValue Op, SelectionDAG &DAG) const; 371 SDValue lowerINTRINSIC_W_CHAIN(SDValue Op, SelectionDAG &DAG) const; 372 SDValue lowerINTRINSIC_VOID(SDValue Op, SelectionDAG &DAG) const; 373 SDValue lowerFRAMEADDR(SDValue Op, SelectionDAG &DAG) const; 374 SDValue lowerRETURNADDR(SDValue Op, SelectionDAG &DAG) const; 375 SDValue lowerWRITE_REGISTER(SDValue Op, SelectionDAG &DAG) const; 376 SDValue lowerEXTRACT_VECTOR_ELT(SDValue Op, SelectionDAG &DAG) const; 377 SDValue lowerINSERT_VECTOR_ELT(SDValue Op, SelectionDAG &DAG) const; 378 SDValue lowerBUILD_VECTOR(SDValue Op, SelectionDAG &DAG) const; 379 SDValue lowerCONCAT_VECTORS(SDValue Op, SelectionDAG &DAG) const; 380 SDValue lowerVECTOR_SHUFFLE(SDValue Op, SelectionDAG &DAG) const; 381 SDValue lowerBITREVERSE(SDValue Op, SelectionDAG &DAG) const; 382 SDValue lowerSCALAR_TO_VECTOR(SDValue Op, SelectionDAG &DAG) const; 383 SDValue lowerPREFETCH(SDValue Op, SelectionDAG &DAG) const; 384 SDValue lowerSELECT(SDValue Op, SelectionDAG &DAG) const; 385 SDValue lowerFP_TO_FP16(SDValue Op, SelectionDAG &DAG) const; 386 SDValue lowerFP16_TO_FP(SDValue Op, SelectionDAG &DAG) const; 387 SDValue lowerFP_TO_BF16(SDValue Op, SelectionDAG &DAG) const; 388 SDValue lowerBF16_TO_FP(SDValue Op, SelectionDAG &DAG) const; 389 390 bool isFPImmLegal(const APFloat &Imm, EVT VT, 391 bool ForCodeSize) const override; 392 393 bool shouldInsertFencesForAtomic(const Instruction *I) const override; 394 395 ConstraintType getConstraintType(StringRef Constraint) const override; 396 397 InlineAsm::ConstraintCode 398 getInlineAsmMemConstraint(StringRef ConstraintCode) const override; 399 400 std::pair<unsigned, const TargetRegisterClass *> 401 getRegForInlineAsmConstraint(const TargetRegisterInfo *TRI, 402 StringRef Constraint, MVT VT) const override; 403 404 void LowerAsmOperandForConstraint(SDValue Op, StringRef Constraint, 405 std::vector<SDValue> &Ops, 406 SelectionDAG &DAG) const override; 407 408 bool isEligibleForTailCallOptimization( 409 CCState &CCInfo, CallLoweringInfo &CLI, MachineFunction &MF, 410 const SmallVectorImpl<CCValAssign> &ArgLocs) const; 411 softPromoteHalfType()412 bool softPromoteHalfType() const override { return true; } 413 414 bool 415 splitValueIntoRegisterParts(SelectionDAG &DAG, const SDLoc &DL, SDValue Val, 416 SDValue *Parts, unsigned NumParts, MVT PartVT, 417 std::optional<CallingConv::ID> CC) const override; 418 419 SDValue 420 joinRegisterPartsIntoValue(SelectionDAG &DAG, const SDLoc &DL, 421 const SDValue *Parts, unsigned NumParts, 422 MVT PartVT, EVT ValueVT, 423 std::optional<CallingConv::ID> CC) const override; 424 425 /// Return the register type for a given MVT, ensuring vectors are treated 426 /// as a series of gpr sized integers. 427 MVT getRegisterTypeForCallingConv(LLVMContext &Context, CallingConv::ID CC, 428 EVT VT) const override; 429 430 /// Return the number of registers for a given MVT, ensuring vectors are 431 /// treated as a series of gpr sized integers. 432 unsigned getNumRegistersForCallingConv(LLVMContext &Context, 433 CallingConv::ID CC, 434 EVT VT) const override; 435 }; 436 437 } // end namespace llvm 438 439 #endif // LLVM_LIB_TARGET_LOONGARCH_LOONGARCHISELLOWERING_H 440