| 1 | //===-- RISCVISelLowering.h - RISC-V 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 RISC-V uses to lower LLVM code into a |
| 10 | // selection DAG. |
| 11 | // |
| 12 | //===----------------------------------------------------------------------===// |
| 13 | |
| 14 | #ifndef LLVM_LIB_TARGET_RISCV_RISCVISELLOWERING_H |
| 15 | #define LLVM_LIB_TARGET_RISCV_RISCVISELLOWERING_H |
| 16 | |
| 17 | #include "RISCV.h" |
| 18 | #include "RISCVCallingConv.h" |
| 19 | #include "llvm/CodeGen/CallingConvLower.h" |
| 20 | #include "llvm/CodeGen/SelectionDAG.h" |
| 21 | #include "llvm/CodeGen/TargetLowering.h" |
| 22 | #include <optional> |
| 23 | |
| 24 | namespace llvm { |
| 25 | class InstructionCost; |
| 26 | class RISCVSubtarget; |
| 27 | struct RISCVRegisterInfo; |
| 28 | |
| 29 | class RISCVTargetLowering : public TargetLowering { |
| 30 | const RISCVSubtarget &Subtarget; |
| 31 | |
| 32 | public: |
| 33 | explicit RISCVTargetLowering(const TargetMachine &TM, |
| 34 | const RISCVSubtarget &STI); |
| 35 | |
| 36 | const RISCVSubtarget &getSubtarget() const { return Subtarget; } |
| 37 | |
| 38 | bool getTgtMemIntrinsic(IntrinsicInfo &Info, const CallInst &I, |
| 39 | MachineFunction &MF, |
| 40 | unsigned Intrinsic) const override; |
| 41 | bool isLegalAddressingMode(const DataLayout &DL, const AddrMode &AM, Type *Ty, |
| 42 | unsigned AS, |
| 43 | Instruction *I = nullptr) const override; |
| 44 | bool isLegalICmpImmediate(int64_t Imm) const override; |
| 45 | bool isLegalAddImmediate(int64_t Imm) const override; |
| 46 | bool isTruncateFree(Type *SrcTy, Type *DstTy) const override; |
| 47 | bool isTruncateFree(EVT SrcVT, EVT DstVT) const override; |
| 48 | bool isTruncateFree(SDValue Val, EVT VT2) const override; |
| 49 | bool isZExtFree(SDValue Val, EVT VT2) const override; |
| 50 | bool isSExtCheaperThanZExt(EVT SrcVT, EVT DstVT) const override; |
| 51 | bool signExtendConstant(const ConstantInt *CI) const override; |
| 52 | bool isCheapToSpeculateCttz(Type *Ty) const override; |
| 53 | bool isCheapToSpeculateCtlz(Type *Ty) const override; |
| 54 | bool isMaskAndCmp0FoldingBeneficial(const Instruction &AndI) const override; |
| 55 | bool hasAndNotCompare(SDValue Y) const override; |
| 56 | bool hasAndNot(SDValue Y) const override; |
| 57 | bool hasBitTest(SDValue X, SDValue Y) const override; |
| 58 | bool shouldProduceAndByConstByHoistingConstFromShiftsLHSOfAnd( |
| 59 | SDValue X, ConstantSDNode *XC, ConstantSDNode *CC, SDValue Y, |
| 60 | unsigned OldShiftOpcode, unsigned NewShiftOpcode, |
| 61 | SelectionDAG &DAG) const override; |
| 62 | bool shouldScalarizeBinop(SDValue VecOp) const override; |
| 63 | bool isOffsetFoldingLegal(const GlobalAddressSDNode *GA) const override; |
| 64 | int getLegalZfaFPImm(const APFloat &Imm, EVT VT) const; |
| 65 | bool isFPImmLegal(const APFloat &Imm, EVT VT, |
| 66 | bool ForCodeSize) const override; |
| 67 | bool (EVT ResVT, EVT SrcVT, |
| 68 | unsigned Index) const override; |
| 69 | |
| 70 | bool isIntDivCheap(EVT VT, AttributeList Attr) const override; |
| 71 | |
| 72 | bool preferScalarizeSplat(SDNode *N) const override; |
| 73 | |
| 74 | bool softPromoteHalfType() const override { return true; } |
| 75 | |
| 76 | /// Return the register type for a given MVT, ensuring vectors are treated |
| 77 | /// as a series of gpr sized integers. |
| 78 | MVT getRegisterTypeForCallingConv(LLVMContext &Context, CallingConv::ID CC, |
| 79 | EVT VT) const override; |
| 80 | |
| 81 | /// Return the number of registers for a given MVT, for inline assembly |
| 82 | unsigned |
| 83 | getNumRegisters(LLVMContext &Context, EVT VT, |
| 84 | std::optional<MVT> RegisterVT = std::nullopt) const override; |
| 85 | |
| 86 | /// Return the number of registers for a given MVT, ensuring vectors are |
| 87 | /// treated as a series of gpr sized integers. |
| 88 | unsigned getNumRegistersForCallingConv(LLVMContext &Context, |
| 89 | CallingConv::ID CC, |
| 90 | EVT VT) const override; |
| 91 | |
| 92 | unsigned getVectorTypeBreakdownForCallingConv(LLVMContext &Context, |
| 93 | CallingConv::ID CC, EVT VT, |
| 94 | EVT &IntermediateVT, |
| 95 | unsigned &NumIntermediates, |
| 96 | MVT &RegisterVT) const override; |
| 97 | |
| 98 | bool shouldFoldSelectWithIdentityConstant(unsigned BinOpcode, EVT VT, |
| 99 | unsigned SelectOpcode, SDValue X, |
| 100 | SDValue Y) const override; |
| 101 | |
| 102 | /// Return true if the given shuffle mask can be codegen'd directly, or if it |
| 103 | /// should be stack expanded. |
| 104 | bool isShuffleMaskLegal(ArrayRef<int> M, EVT VT) const override; |
| 105 | |
| 106 | bool isMultiStoresCheaperThanBitsMerge(EVT LTy, EVT HTy) const override { |
| 107 | // If the pair to store is a mixture of float and int values, we will |
| 108 | // save two bitwise instructions and one float-to-int instruction and |
| 109 | // increase one store instruction. There is potentially a more |
| 110 | // significant benefit because it avoids the float->int domain switch |
| 111 | // for input value. So It is more likely a win. |
| 112 | if ((LTy.isFloatingPoint() && HTy.isInteger()) || |
| 113 | (LTy.isInteger() && HTy.isFloatingPoint())) |
| 114 | return true; |
| 115 | // If the pair only contains int values, we will save two bitwise |
| 116 | // instructions and increase one store instruction (costing one more |
| 117 | // store buffer). Since the benefit is more blurred we leave such a pair |
| 118 | // out until we get testcase to prove it is a win. |
| 119 | return false; |
| 120 | } |
| 121 | |
| 122 | bool |
| 123 | shouldExpandBuildVectorWithShuffles(EVT VT, |
| 124 | unsigned DefinedValues) const override; |
| 125 | |
| 126 | bool shouldExpandCttzElements(EVT VT) const override; |
| 127 | |
| 128 | /// Return the cost of LMUL for linear operations. |
| 129 | InstructionCost getLMULCost(MVT VT) const; |
| 130 | |
| 131 | InstructionCost getVRGatherVVCost(MVT VT) const; |
| 132 | InstructionCost getVRGatherVICost(MVT VT) const; |
| 133 | InstructionCost getVSlideVXCost(MVT VT) const; |
| 134 | InstructionCost getVSlideVICost(MVT VT) const; |
| 135 | |
| 136 | // Provide custom lowering hooks for some operations. |
| 137 | SDValue LowerOperation(SDValue Op, SelectionDAG &DAG) const override; |
| 138 | void ReplaceNodeResults(SDNode *N, SmallVectorImpl<SDValue> &Results, |
| 139 | SelectionDAG &DAG) const override; |
| 140 | |
| 141 | SDValue PerformDAGCombine(SDNode *N, DAGCombinerInfo &DCI) const override; |
| 142 | |
| 143 | bool targetShrinkDemandedConstant(SDValue Op, const APInt &DemandedBits, |
| 144 | const APInt &DemandedElts, |
| 145 | TargetLoweringOpt &TLO) const override; |
| 146 | |
| 147 | void computeKnownBitsForTargetNode(const SDValue Op, |
| 148 | KnownBits &Known, |
| 149 | const APInt &DemandedElts, |
| 150 | const SelectionDAG &DAG, |
| 151 | unsigned Depth) const override; |
| 152 | unsigned ComputeNumSignBitsForTargetNode(SDValue Op, |
| 153 | const APInt &DemandedElts, |
| 154 | const SelectionDAG &DAG, |
| 155 | unsigned Depth) const override; |
| 156 | |
| 157 | bool SimplifyDemandedBitsForTargetNode(SDValue Op, const APInt &DemandedBits, |
| 158 | const APInt &DemandedElts, |
| 159 | KnownBits &Known, |
| 160 | TargetLoweringOpt &TLO, |
| 161 | unsigned Depth) const override; |
| 162 | |
| 163 | bool canCreateUndefOrPoisonForTargetNode(SDValue Op, |
| 164 | const APInt &DemandedElts, |
| 165 | const SelectionDAG &DAG, |
| 166 | bool PoisonOnly, bool ConsiderFlags, |
| 167 | unsigned Depth) const override; |
| 168 | |
| 169 | const Constant *getTargetConstantFromLoad(LoadSDNode *LD) const override; |
| 170 | |
| 171 | MachineMemOperand::Flags |
| 172 | getTargetMMOFlags(const Instruction &I) const override; |
| 173 | |
| 174 | MachineMemOperand::Flags |
| 175 | getTargetMMOFlags(const MemSDNode &Node) const override; |
| 176 | |
| 177 | bool |
| 178 | areTwoSDNodeTargetMMOFlagsMergeable(const MemSDNode &NodeX, |
| 179 | const MemSDNode &NodeY) const override; |
| 180 | |
| 181 | ConstraintType getConstraintType(StringRef Constraint) const override; |
| 182 | |
| 183 | InlineAsm::ConstraintCode |
| 184 | getInlineAsmMemConstraint(StringRef ConstraintCode) const override; |
| 185 | |
| 186 | std::pair<unsigned, const TargetRegisterClass *> |
| 187 | getRegForInlineAsmConstraint(const TargetRegisterInfo *TRI, |
| 188 | StringRef Constraint, MVT VT) const override; |
| 189 | |
| 190 | void LowerAsmOperandForConstraint(SDValue Op, StringRef Constraint, |
| 191 | std::vector<SDValue> &Ops, |
| 192 | SelectionDAG &DAG) const override; |
| 193 | |
| 194 | MachineBasicBlock * |
| 195 | EmitInstrWithCustomInserter(MachineInstr &MI, |
| 196 | MachineBasicBlock *BB) const override; |
| 197 | |
| 198 | void AdjustInstrPostInstrSelection(MachineInstr &MI, |
| 199 | SDNode *Node) const override; |
| 200 | |
| 201 | EVT getSetCCResultType(const DataLayout &DL, LLVMContext &Context, |
| 202 | EVT VT) const override; |
| 203 | |
| 204 | bool shouldFormOverflowOp(unsigned Opcode, EVT VT, |
| 205 | bool MathUsed) const override { |
| 206 | if (VT == MVT::i8 || VT == MVT::i16) |
| 207 | return false; |
| 208 | |
| 209 | return TargetLowering::shouldFormOverflowOp(Opcode, VT, MathUsed); |
| 210 | } |
| 211 | |
| 212 | bool storeOfVectorConstantIsCheap(bool IsZero, EVT MemVT, unsigned NumElem, |
| 213 | unsigned AddrSpace) const override { |
| 214 | // If we can replace 4 or more scalar stores, there will be a reduction |
| 215 | // in instructions even after we add a vector constant load. |
| 216 | return NumElem >= 4; |
| 217 | } |
| 218 | |
| 219 | bool convertSetCCLogicToBitwiseLogic(EVT VT) const override { |
| 220 | return VT.isScalarInteger(); |
| 221 | } |
| 222 | bool convertSelectOfConstantsToMath(EVT VT) const override { return true; } |
| 223 | |
| 224 | bool isCtpopFast(EVT VT) const override; |
| 225 | |
| 226 | unsigned getCustomCtpopCost(EVT VT, ISD::CondCode Cond) const override; |
| 227 | |
| 228 | bool preferZeroCompareBranch() const override { return true; } |
| 229 | |
| 230 | // Note that one specific case requires fence insertion for an |
| 231 | // AtomicCmpXchgInst but is handled via the RISCVZacasABIFix pass rather |
| 232 | // than this hook due to limitations in the interface here. |
| 233 | bool shouldInsertFencesForAtomic(const Instruction *I) const override; |
| 234 | |
| 235 | Instruction *emitLeadingFence(IRBuilderBase &Builder, Instruction *Inst, |
| 236 | AtomicOrdering Ord) const override; |
| 237 | Instruction *emitTrailingFence(IRBuilderBase &Builder, Instruction *Inst, |
| 238 | AtomicOrdering Ord) const override; |
| 239 | |
| 240 | bool isFMAFasterThanFMulAndFAdd(const MachineFunction &MF, |
| 241 | EVT VT) const override; |
| 242 | |
| 243 | ISD::NodeType getExtendForAtomicOps() const override { |
| 244 | return ISD::SIGN_EXTEND; |
| 245 | } |
| 246 | |
| 247 | ISD::NodeType getExtendForAtomicCmpSwapArg() const override; |
| 248 | |
| 249 | bool shouldTransformSignedTruncationCheck(EVT XVT, |
| 250 | unsigned KeptBits) const override; |
| 251 | |
| 252 | TargetLowering::ShiftLegalizationStrategy |
| 253 | preferredShiftLegalizationStrategy(SelectionDAG &DAG, SDNode *N, |
| 254 | unsigned ExpansionFactor) const override { |
| 255 | if (DAG.getMachineFunction().getFunction().hasMinSize()) |
| 256 | return ShiftLegalizationStrategy::LowerToLibcall; |
| 257 | return TargetLowering::preferredShiftLegalizationStrategy(DAG, N, |
| 258 | ExpansionFactor); |
| 259 | } |
| 260 | |
| 261 | bool isDesirableToCommuteWithShift(const SDNode *N, |
| 262 | CombineLevel Level) const override; |
| 263 | |
| 264 | /// If a physical register, this returns the register that receives the |
| 265 | /// exception address on entry to an EH pad. |
| 266 | Register |
| 267 | getExceptionPointerRegister(const Constant *PersonalityFn) const override; |
| 268 | |
| 269 | /// If a physical register, this returns the register that receives the |
| 270 | /// exception typeid on entry to a landing pad. |
| 271 | Register |
| 272 | getExceptionSelectorRegister(const Constant *PersonalityFn) const override; |
| 273 | |
| 274 | bool shouldExtendTypeInLibCall(EVT Type) const override; |
| 275 | bool shouldSignExtendTypeInLibCall(Type *Ty, bool IsSigned) const override; |
| 276 | |
| 277 | /// Returns the register with the specified architectural or ABI name. This |
| 278 | /// method is necessary to lower the llvm.read_register.* and |
| 279 | /// llvm.write_register.* intrinsics. Allocatable registers must be reserved |
| 280 | /// with the clang -ffixed-xX flag for access to be allowed. |
| 281 | Register getRegisterByName(const char *RegName, LLT VT, |
| 282 | const MachineFunction &MF) const override; |
| 283 | |
| 284 | // Lower incoming arguments, copy physregs into vregs |
| 285 | SDValue LowerFormalArguments(SDValue Chain, CallingConv::ID CallConv, |
| 286 | bool IsVarArg, |
| 287 | const SmallVectorImpl<ISD::InputArg> &Ins, |
| 288 | const SDLoc &DL, SelectionDAG &DAG, |
| 289 | SmallVectorImpl<SDValue> &InVals) const override; |
| 290 | bool CanLowerReturn(CallingConv::ID CallConv, MachineFunction &MF, |
| 291 | bool IsVarArg, |
| 292 | const SmallVectorImpl<ISD::OutputArg> &Outs, |
| 293 | LLVMContext &Context, const Type *RetTy) const override; |
| 294 | SDValue LowerReturn(SDValue Chain, CallingConv::ID CallConv, bool IsVarArg, |
| 295 | const SmallVectorImpl<ISD::OutputArg> &Outs, |
| 296 | const SmallVectorImpl<SDValue> &OutVals, const SDLoc &DL, |
| 297 | SelectionDAG &DAG) const override; |
| 298 | SDValue LowerCall(TargetLowering::CallLoweringInfo &CLI, |
| 299 | SmallVectorImpl<SDValue> &InVals) const override; |
| 300 | |
| 301 | bool shouldConvertConstantLoadToIntImm(const APInt &Imm, |
| 302 | Type *Ty) const override; |
| 303 | bool isUsedByReturnOnly(SDNode *N, SDValue &Chain) const override; |
| 304 | bool mayBeEmittedAsTailCall(const CallInst *CI) const override; |
| 305 | bool shouldConsiderGEPOffsetSplit() const override { return true; } |
| 306 | |
| 307 | bool decomposeMulByConstant(LLVMContext &Context, EVT VT, |
| 308 | SDValue C) const override; |
| 309 | |
| 310 | bool isMulAddWithConstProfitable(SDValue AddNode, |
| 311 | SDValue ConstNode) const override; |
| 312 | |
| 313 | TargetLowering::AtomicExpansionKind |
| 314 | shouldExpandAtomicRMWInIR(AtomicRMWInst *AI) const override; |
| 315 | Value *emitMaskedAtomicRMWIntrinsic(IRBuilderBase &Builder, AtomicRMWInst *AI, |
| 316 | Value *AlignedAddr, Value *Incr, |
| 317 | Value *Mask, Value *ShiftAmt, |
| 318 | AtomicOrdering Ord) const override; |
| 319 | TargetLowering::AtomicExpansionKind |
| 320 | shouldExpandAtomicCmpXchgInIR(AtomicCmpXchgInst *CI) const override; |
| 321 | Value *emitMaskedAtomicCmpXchgIntrinsic(IRBuilderBase &Builder, |
| 322 | AtomicCmpXchgInst *CI, |
| 323 | Value *AlignedAddr, Value *CmpVal, |
| 324 | Value *NewVal, Value *Mask, |
| 325 | AtomicOrdering Ord) const override; |
| 326 | |
| 327 | /// Returns true if the target allows unaligned memory accesses of the |
| 328 | /// specified type. |
| 329 | bool allowsMisalignedMemoryAccesses( |
| 330 | EVT VT, unsigned AddrSpace = 0, Align Alignment = Align(1), |
| 331 | MachineMemOperand::Flags Flags = MachineMemOperand::MONone, |
| 332 | unsigned *Fast = nullptr) const override; |
| 333 | |
| 334 | EVT getOptimalMemOpType(const MemOp &Op, |
| 335 | const AttributeList &FuncAttributes) const override; |
| 336 | |
| 337 | bool splitValueIntoRegisterParts( |
| 338 | SelectionDAG & DAG, const SDLoc &DL, SDValue Val, SDValue *Parts, |
| 339 | unsigned NumParts, MVT PartVT, std::optional<CallingConv::ID> CC) |
| 340 | const override; |
| 341 | |
| 342 | SDValue joinRegisterPartsIntoValue( |
| 343 | SelectionDAG & DAG, const SDLoc &DL, const SDValue *Parts, |
| 344 | unsigned NumParts, MVT PartVT, EVT ValueVT, |
| 345 | std::optional<CallingConv::ID> CC) const override; |
| 346 | |
| 347 | // Return the value of VLMax for the given vector type (i.e. SEW and LMUL) |
| 348 | SDValue computeVLMax(MVT VecVT, const SDLoc &DL, SelectionDAG &DAG) const; |
| 349 | |
| 350 | static RISCVVType::VLMUL getLMUL(MVT VT); |
| 351 | inline static unsigned computeVLMAX(unsigned VectorBits, unsigned EltSize, |
| 352 | unsigned MinSize) { |
| 353 | // Original equation: |
| 354 | // VLMAX = (VectorBits / EltSize) * LMUL |
| 355 | // where LMUL = MinSize / RISCV::RVVBitsPerBlock |
| 356 | // The following equations have been reordered to prevent loss of precision |
| 357 | // when calculating fractional LMUL. |
| 358 | return ((VectorBits / EltSize) * MinSize) / RISCV::RVVBitsPerBlock; |
| 359 | } |
| 360 | |
| 361 | // Return inclusive (low, high) bounds on the value of VLMAX for the |
| 362 | // given scalable container type given known bounds on VLEN. |
| 363 | static std::pair<unsigned, unsigned> |
| 364 | computeVLMAXBounds(MVT ContainerVT, const RISCVSubtarget &Subtarget); |
| 365 | |
| 366 | /// Given a vector (either fixed or scalable), return the scalable vector |
| 367 | /// corresponding to a vector register (i.e. an m1 register group). |
| 368 | static MVT getM1VT(MVT VT) { |
| 369 | unsigned EltSizeInBits = VT.getVectorElementType().getSizeInBits(); |
| 370 | assert(EltSizeInBits <= RISCV::RVVBitsPerBlock && "Unexpected vector MVT" ); |
| 371 | return MVT::getScalableVectorVT(VT: VT.getVectorElementType(), |
| 372 | NumElements: RISCV::RVVBitsPerBlock / EltSizeInBits); |
| 373 | } |
| 374 | |
| 375 | static unsigned getRegClassIDForLMUL(RISCVVType::VLMUL LMul); |
| 376 | static unsigned getSubregIndexByMVT(MVT VT, unsigned Index); |
| 377 | static unsigned getRegClassIDForVecVT(MVT VT); |
| 378 | static std::pair<unsigned, unsigned> |
| 379 | (MVT VecVT, MVT SubVecVT, |
| 380 | unsigned , |
| 381 | const RISCVRegisterInfo *TRI); |
| 382 | MVT getContainerForFixedLengthVector(MVT VT) const; |
| 383 | |
| 384 | bool shouldRemoveExtendFromGSIndex(SDValue Extend, EVT DataVT) const override; |
| 385 | |
| 386 | bool isLegalElementTypeForRVV(EVT ScalarTy) const; |
| 387 | |
| 388 | bool shouldConvertFpToSat(unsigned Op, EVT FPVT, EVT VT) const override; |
| 389 | |
| 390 | unsigned getJumpTableEncoding() const override; |
| 391 | |
| 392 | const MCExpr *LowerCustomJumpTableEntry(const MachineJumpTableInfo *MJTI, |
| 393 | const MachineBasicBlock *MBB, |
| 394 | unsigned uid, |
| 395 | MCContext &Ctx) const override; |
| 396 | |
| 397 | bool isVScaleKnownToBeAPowerOfTwo() const override; |
| 398 | |
| 399 | bool getIndexedAddressParts(SDNode *Op, SDValue &Base, SDValue &Offset, |
| 400 | ISD::MemIndexedMode &AM, SelectionDAG &DAG) const; |
| 401 | bool getPreIndexedAddressParts(SDNode *N, SDValue &Base, SDValue &Offset, |
| 402 | ISD::MemIndexedMode &AM, |
| 403 | SelectionDAG &DAG) const override; |
| 404 | bool getPostIndexedAddressParts(SDNode *N, SDNode *Op, SDValue &Base, |
| 405 | SDValue &Offset, ISD::MemIndexedMode &AM, |
| 406 | SelectionDAG &DAG) const override; |
| 407 | |
| 408 | bool isLegalScaleForGatherScatter(uint64_t Scale, |
| 409 | uint64_t ElemSize) const override { |
| 410 | // Scaled addressing not supported on indexed load/stores |
| 411 | return Scale == 1; |
| 412 | } |
| 413 | |
| 414 | /// If the target has a standard location for the stack protector cookie, |
| 415 | /// returns the address of that location. Otherwise, returns nullptr. |
| 416 | Value *getIRStackGuard(IRBuilderBase &IRB) const override; |
| 417 | |
| 418 | /// Returns whether or not generating a interleaved load/store intrinsic for |
| 419 | /// this type will be legal. |
| 420 | bool isLegalInterleavedAccessType(VectorType *VTy, unsigned Factor, |
| 421 | Align Alignment, unsigned AddrSpace, |
| 422 | const DataLayout &) const; |
| 423 | |
| 424 | /// Return true if a stride load store of the given result type and |
| 425 | /// alignment is legal. |
| 426 | bool isLegalStridedLoadStore(EVT DataType, Align Alignment) const; |
| 427 | |
| 428 | unsigned getMaxSupportedInterleaveFactor() const override { return 8; } |
| 429 | |
| 430 | bool fallBackToDAGISel(const Instruction &Inst) const override; |
| 431 | |
| 432 | bool lowerInterleavedLoad(LoadInst *LI, |
| 433 | ArrayRef<ShuffleVectorInst *> Shuffles, |
| 434 | ArrayRef<unsigned> Indices, |
| 435 | unsigned Factor) const override; |
| 436 | |
| 437 | bool lowerInterleavedStore(StoreInst *SI, ShuffleVectorInst *SVI, |
| 438 | unsigned Factor) const override; |
| 439 | |
| 440 | bool lowerDeinterleaveIntrinsicToLoad( |
| 441 | LoadInst *LI, ArrayRef<Value *> DeinterleaveValues) const override; |
| 442 | |
| 443 | bool lowerInterleaveIntrinsicToStore( |
| 444 | StoreInst *SI, ArrayRef<Value *> InterleaveValues) const override; |
| 445 | |
| 446 | bool lowerInterleavedVPLoad(VPIntrinsic *Load, Value *Mask, |
| 447 | ArrayRef<Value *> DeinterleaveRes) const override; |
| 448 | |
| 449 | bool lowerInterleavedVPStore(VPIntrinsic *Store, Value *Mask, |
| 450 | ArrayRef<Value *> InterleaveOps) const override; |
| 451 | |
| 452 | bool supportKCFIBundles() const override { return true; } |
| 453 | |
| 454 | SDValue expandIndirectJTBranch(const SDLoc &dl, SDValue Value, SDValue Addr, |
| 455 | int JTI, SelectionDAG &DAG) const override; |
| 456 | |
| 457 | MachineInstr *EmitKCFICheck(MachineBasicBlock &MBB, |
| 458 | MachineBasicBlock::instr_iterator &MBBI, |
| 459 | const TargetInstrInfo *TII) const override; |
| 460 | |
| 461 | /// True if stack clash protection is enabled for this functions. |
| 462 | bool hasInlineStackProbe(const MachineFunction &MF) const override; |
| 463 | |
| 464 | unsigned getStackProbeSize(const MachineFunction &MF, Align StackAlign) const; |
| 465 | |
| 466 | MachineBasicBlock *emitDynamicProbedAlloc(MachineInstr &MI, |
| 467 | MachineBasicBlock *MBB) const; |
| 468 | |
| 469 | ArrayRef<MCPhysReg> getRoundingControlRegisters() const override; |
| 470 | |
| 471 | private: |
| 472 | void analyzeInputArgs(MachineFunction &MF, CCState &CCInfo, |
| 473 | const SmallVectorImpl<ISD::InputArg> &Ins, bool IsRet, |
| 474 | RISCVCCAssignFn Fn) const; |
| 475 | void analyzeOutputArgs(MachineFunction &MF, CCState &CCInfo, |
| 476 | const SmallVectorImpl<ISD::OutputArg> &Outs, |
| 477 | bool IsRet, CallLoweringInfo *CLI, |
| 478 | RISCVCCAssignFn Fn) const; |
| 479 | |
| 480 | template <class NodeTy> |
| 481 | SDValue getAddr(NodeTy *N, SelectionDAG &DAG, bool IsLocal = true, |
| 482 | bool IsExternWeak = false) const; |
| 483 | SDValue getStaticTLSAddr(GlobalAddressSDNode *N, SelectionDAG &DAG, |
| 484 | bool UseGOT) const; |
| 485 | SDValue getDynamicTLSAddr(GlobalAddressSDNode *N, SelectionDAG &DAG) const; |
| 486 | SDValue getTLSDescAddr(GlobalAddressSDNode *N, SelectionDAG &DAG) const; |
| 487 | |
| 488 | SDValue lowerConstantFP(SDValue Op, SelectionDAG &DAG) const; |
| 489 | SDValue lowerGlobalAddress(SDValue Op, SelectionDAG &DAG) const; |
| 490 | SDValue lowerBlockAddress(SDValue Op, SelectionDAG &DAG) const; |
| 491 | SDValue lowerConstantPool(SDValue Op, SelectionDAG &DAG) const; |
| 492 | SDValue lowerJumpTable(SDValue Op, SelectionDAG &DAG) const; |
| 493 | SDValue lowerGlobalTLSAddress(SDValue Op, SelectionDAG &DAG) const; |
| 494 | SDValue lowerSELECT(SDValue Op, SelectionDAG &DAG) const; |
| 495 | SDValue lowerBRCOND(SDValue Op, SelectionDAG &DAG) const; |
| 496 | SDValue lowerVASTART(SDValue Op, SelectionDAG &DAG) const; |
| 497 | SDValue lowerFRAMEADDR(SDValue Op, SelectionDAG &DAG) const; |
| 498 | SDValue lowerRETURNADDR(SDValue Op, SelectionDAG &DAG) const; |
| 499 | SDValue lowerShiftLeftParts(SDValue Op, SelectionDAG &DAG) const; |
| 500 | SDValue lowerShiftRightParts(SDValue Op, SelectionDAG &DAG, bool IsSRA) const; |
| 501 | SDValue lowerSPLAT_VECTOR_PARTS(SDValue Op, SelectionDAG &DAG) const; |
| 502 | SDValue lowerVectorMaskSplat(SDValue Op, SelectionDAG &DAG) const; |
| 503 | SDValue lowerVectorMaskExt(SDValue Op, SelectionDAG &DAG, |
| 504 | int64_t ExtTrueVal) const; |
| 505 | SDValue lowerVectorMaskTruncLike(SDValue Op, SelectionDAG &DAG) const; |
| 506 | SDValue lowerVectorTruncLike(SDValue Op, SelectionDAG &DAG) const; |
| 507 | SDValue lowerVectorFPExtendOrRoundLike(SDValue Op, SelectionDAG &DAG) const; |
| 508 | SDValue lowerINSERT_VECTOR_ELT(SDValue Op, SelectionDAG &DAG) const; |
| 509 | SDValue (SDValue Op, SelectionDAG &DAG) const; |
| 510 | SDValue LowerINTRINSIC_WO_CHAIN(SDValue Op, SelectionDAG &DAG) const; |
| 511 | SDValue LowerINTRINSIC_W_CHAIN(SDValue Op, SelectionDAG &DAG) const; |
| 512 | SDValue LowerINTRINSIC_VOID(SDValue Op, SelectionDAG &DAG) const; |
| 513 | SDValue lowerVPREDUCE(SDValue Op, SelectionDAG &DAG) const; |
| 514 | SDValue lowerVECREDUCE(SDValue Op, SelectionDAG &DAG) const; |
| 515 | SDValue lowerVectorMaskVecReduction(SDValue Op, SelectionDAG &DAG, |
| 516 | bool IsVP) const; |
| 517 | SDValue lowerFPVECREDUCE(SDValue Op, SelectionDAG &DAG) const; |
| 518 | SDValue lowerINSERT_SUBVECTOR(SDValue Op, SelectionDAG &DAG) const; |
| 519 | SDValue (SDValue Op, SelectionDAG &DAG) const; |
| 520 | SDValue lowerVECTOR_DEINTERLEAVE(SDValue Op, SelectionDAG &DAG) const; |
| 521 | SDValue lowerVECTOR_INTERLEAVE(SDValue Op, SelectionDAG &DAG) const; |
| 522 | SDValue lowerSTEP_VECTOR(SDValue Op, SelectionDAG &DAG) const; |
| 523 | SDValue lowerVECTOR_REVERSE(SDValue Op, SelectionDAG &DAG) const; |
| 524 | SDValue lowerVECTOR_SPLICE(SDValue Op, SelectionDAG &DAG) const; |
| 525 | SDValue lowerABS(SDValue Op, SelectionDAG &DAG) const; |
| 526 | SDValue lowerMaskedLoad(SDValue Op, SelectionDAG &DAG) const; |
| 527 | SDValue lowerMaskedStore(SDValue Op, SelectionDAG &DAG) const; |
| 528 | SDValue lowerVectorCompress(SDValue Op, SelectionDAG &DAG) const; |
| 529 | SDValue lowerFixedLengthVectorFCOPYSIGNToRVV(SDValue Op, |
| 530 | SelectionDAG &DAG) const; |
| 531 | SDValue lowerMaskedGather(SDValue Op, SelectionDAG &DAG) const; |
| 532 | SDValue lowerMaskedScatter(SDValue Op, SelectionDAG &DAG) const; |
| 533 | SDValue lowerFixedLengthVectorLoadToRVV(SDValue Op, SelectionDAG &DAG) const; |
| 534 | SDValue lowerFixedLengthVectorStoreToRVV(SDValue Op, SelectionDAG &DAG) const; |
| 535 | SDValue lowerFixedLengthVectorSetccToRVV(SDValue Op, SelectionDAG &DAG) const; |
| 536 | SDValue lowerFixedLengthVectorSelectToRVV(SDValue Op, |
| 537 | SelectionDAG &DAG) const; |
| 538 | SDValue lowerToScalableOp(SDValue Op, SelectionDAG &DAG) const; |
| 539 | SDValue LowerIS_FPCLASS(SDValue Op, SelectionDAG &DAG) const; |
| 540 | SDValue lowerVPOp(SDValue Op, SelectionDAG &DAG) const; |
| 541 | SDValue lowerLogicVPOp(SDValue Op, SelectionDAG &DAG) const; |
| 542 | SDValue lowerVPExtMaskOp(SDValue Op, SelectionDAG &DAG) const; |
| 543 | SDValue lowerVPSetCCMaskOp(SDValue Op, SelectionDAG &DAG) const; |
| 544 | SDValue lowerVPMergeMask(SDValue Op, SelectionDAG &DAG) const; |
| 545 | SDValue lowerVPSplatExperimental(SDValue Op, SelectionDAG &DAG) const; |
| 546 | SDValue lowerVPSpliceExperimental(SDValue Op, SelectionDAG &DAG) const; |
| 547 | SDValue lowerVPReverseExperimental(SDValue Op, SelectionDAG &DAG) const; |
| 548 | SDValue lowerVPFPIntConvOp(SDValue Op, SelectionDAG &DAG) const; |
| 549 | SDValue lowerVPStridedLoad(SDValue Op, SelectionDAG &DAG) const; |
| 550 | SDValue lowerVPStridedStore(SDValue Op, SelectionDAG &DAG) const; |
| 551 | SDValue lowerVPCttzElements(SDValue Op, SelectionDAG &DAG) const; |
| 552 | SDValue lowerFixedLengthVectorExtendToRVV(SDValue Op, SelectionDAG &DAG, |
| 553 | unsigned ExtendOpc) const; |
| 554 | SDValue lowerGET_ROUNDING(SDValue Op, SelectionDAG &DAG) const; |
| 555 | SDValue lowerSET_ROUNDING(SDValue Op, SelectionDAG &DAG) const; |
| 556 | SDValue lowerGET_FPENV(SDValue Op, SelectionDAG &DAG) const; |
| 557 | SDValue lowerSET_FPENV(SDValue Op, SelectionDAG &DAG) const; |
| 558 | SDValue lowerRESET_FPENV(SDValue Op, SelectionDAG &DAG) const; |
| 559 | |
| 560 | SDValue lowerEH_DWARF_CFA(SDValue Op, SelectionDAG &DAG) const; |
| 561 | SDValue lowerCTLZ_CTTZ_ZERO_UNDEF(SDValue Op, SelectionDAG &DAG) const; |
| 562 | |
| 563 | SDValue lowerStrictFPExtendOrRoundLike(SDValue Op, SelectionDAG &DAG) const; |
| 564 | |
| 565 | SDValue lowerVectorStrictFSetcc(SDValue Op, SelectionDAG &DAG) const; |
| 566 | |
| 567 | SDValue lowerDYNAMIC_STACKALLOC(SDValue Op, SelectionDAG &DAG) const; |
| 568 | |
| 569 | SDValue expandUnalignedRVVLoad(SDValue Op, SelectionDAG &DAG) const; |
| 570 | SDValue expandUnalignedRVVStore(SDValue Op, SelectionDAG &DAG) const; |
| 571 | |
| 572 | SDValue lowerINIT_TRAMPOLINE(SDValue Op, SelectionDAG &DAG) const; |
| 573 | SDValue lowerADJUST_TRAMPOLINE(SDValue Op, SelectionDAG &DAG) const; |
| 574 | SDValue lowerPARTIAL_REDUCE_MLA(SDValue Op, SelectionDAG &DAG) const; |
| 575 | |
| 576 | bool isEligibleForTailCallOptimization( |
| 577 | CCState &CCInfo, CallLoweringInfo &CLI, MachineFunction &MF, |
| 578 | const SmallVector<CCValAssign, 16> &ArgLocs) const; |
| 579 | |
| 580 | /// Generate error diagnostics if any register used by CC has been marked |
| 581 | /// reserved. |
| 582 | void validateCCReservedRegs( |
| 583 | const SmallVectorImpl<std::pair<llvm::Register, llvm::SDValue>> &Regs, |
| 584 | MachineFunction &MF) const; |
| 585 | |
| 586 | bool useRVVForFixedLengthVectorVT(MVT VT) const; |
| 587 | |
| 588 | MVT getVPExplicitVectorLengthTy() const override; |
| 589 | |
| 590 | bool shouldExpandGetVectorLength(EVT TripCountVT, unsigned VF, |
| 591 | bool IsScalable) const override; |
| 592 | |
| 593 | /// RVV code generation for fixed length vectors does not lower all |
| 594 | /// BUILD_VECTORs. This makes BUILD_VECTOR legalisation a source of stores to |
| 595 | /// merge. However, merging them creates a BUILD_VECTOR that is just as |
| 596 | /// illegal as the original, thus leading to an infinite legalisation loop. |
| 597 | /// NOTE: Once BUILD_VECTOR can be custom lowered for all legal vector types, |
| 598 | /// this override can be removed. |
| 599 | bool mergeStoresAfterLegalization(EVT VT) const override; |
| 600 | |
| 601 | /// Disable normalizing |
| 602 | /// select(N0&N1, X, Y) => select(N0, select(N1, X, Y), Y) and |
| 603 | /// select(N0|N1, X, Y) => select(N0, select(N1, X, Y, Y)) |
| 604 | /// RISC-V doesn't have flags so it's better to perform the and/or in a GPR. |
| 605 | bool shouldNormalizeToSelectSequence(LLVMContext &, EVT) const override { |
| 606 | return false; |
| 607 | } |
| 608 | |
| 609 | /// Disables storing and loading vectors by default when there are function |
| 610 | /// calls between the load and store, since these are more expensive than just |
| 611 | /// using scalars |
| 612 | bool shouldMergeStoreOfLoadsOverCall(EVT SrcVT, EVT MergedVT) const override { |
| 613 | return !MergedVT.isVector() || SrcVT.isVector(); |
| 614 | } |
| 615 | |
| 616 | /// For available scheduling models FDIV + two independent FMULs are much |
| 617 | /// faster than two FDIVs. |
| 618 | unsigned combineRepeatedFPDivisors() const override; |
| 619 | |
| 620 | SDValue BuildSDIVPow2(SDNode *N, const APInt &Divisor, SelectionDAG &DAG, |
| 621 | SmallVectorImpl<SDNode *> &Created) const override; |
| 622 | |
| 623 | bool shouldFoldSelectWithSingleBitTest(EVT VT, |
| 624 | const APInt &AndMask) const override; |
| 625 | |
| 626 | unsigned getMinimumJumpTableEntries() const override; |
| 627 | |
| 628 | SDValue emitFlushICache(SelectionDAG &DAG, SDValue InChain, SDValue Start, |
| 629 | SDValue End, SDValue Flags, SDLoc DL) const; |
| 630 | |
| 631 | std::pair<const TargetRegisterClass *, uint8_t> |
| 632 | findRepresentativeClass(const TargetRegisterInfo *TRI, MVT VT) const override; |
| 633 | }; |
| 634 | |
| 635 | namespace RISCVVIntrinsicsTable { |
| 636 | |
| 637 | struct RISCVVIntrinsicInfo { |
| 638 | unsigned IntrinsicID; |
| 639 | uint8_t ScalarOperand; |
| 640 | uint8_t VLOperand; |
| 641 | bool hasScalarOperand() const { |
| 642 | // 0xF is not valid. See NoScalarOperand in IntrinsicsRISCV.td. |
| 643 | return ScalarOperand != 0xF; |
| 644 | } |
| 645 | bool hasVLOperand() const { |
| 646 | // 0x1F is not valid. See NoVLOperand in IntrinsicsRISCV.td. |
| 647 | return VLOperand != 0x1F; |
| 648 | } |
| 649 | }; |
| 650 | |
| 651 | using namespace RISCV; |
| 652 | |
| 653 | #define GET_RISCVVIntrinsicsTable_DECL |
| 654 | #include "RISCVGenSearchableTables.inc" |
| 655 | #undef GET_RISCVVIntrinsicsTable_DECL |
| 656 | |
| 657 | } // end namespace RISCVVIntrinsicsTable |
| 658 | |
| 659 | } // end namespace llvm |
| 660 | |
| 661 | #endif |
| 662 | |