| 1 | //==-- AArch64ISelLowering.h - AArch64 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 AArch64 uses to lower LLVM code into a |
| 10 | // selection DAG. |
| 11 | // |
| 12 | //===----------------------------------------------------------------------===// |
| 13 | |
| 14 | #ifndef LLVM_LIB_TARGET_AARCH64_AARCH64ISELLOWERING_H |
| 15 | #define LLVM_LIB_TARGET_AARCH64_AARCH64ISELLOWERING_H |
| 16 | |
| 17 | #include "llvm/CodeGen/CallingConvLower.h" |
| 18 | #include "llvm/CodeGen/MachineFunction.h" |
| 19 | #include "llvm/CodeGen/SelectionDAG.h" |
| 20 | #include "llvm/CodeGen/TargetLowering.h" |
| 21 | #include "llvm/IR/CallingConv.h" |
| 22 | #include "llvm/IR/Instruction.h" |
| 23 | |
| 24 | namespace llvm { |
| 25 | |
| 26 | namespace AArch64 { |
| 27 | /// Possible values of current rounding mode, which is specified in bits |
| 28 | /// 23:22 of FPCR. |
| 29 | enum Rounding { |
| 30 | RN = 0, // Round to Nearest |
| 31 | RP = 1, // Round towards Plus infinity |
| 32 | RM = 2, // Round towards Minus infinity |
| 33 | RZ = 3, // Round towards Zero |
| 34 | rmMask = 3 // Bit mask selecting rounding mode |
| 35 | }; |
| 36 | |
| 37 | // Bit position of rounding mode bits in FPCR. |
| 38 | const unsigned RoundingBitsPos = 22; |
| 39 | |
| 40 | // Reserved bits should be preserved when modifying FPCR. |
| 41 | const uint64_t ReservedFPControlBits = 0xfffffffff80040f8; |
| 42 | |
| 43 | // Registers used to pass function arguments. |
| 44 | ArrayRef<MCPhysReg> getGPRArgRegs(); |
| 45 | ArrayRef<MCPhysReg> getFPRArgRegs(); |
| 46 | |
| 47 | /// Maximum allowed number of unprobed bytes above SP at an ABI |
| 48 | /// boundary. |
| 49 | const unsigned StackProbeMaxUnprobedStack = 1024; |
| 50 | |
| 51 | /// Maximum number of iterations to unroll for a constant size probing loop. |
| 52 | const unsigned StackProbeMaxLoopUnroll = 4; |
| 53 | |
| 54 | } // namespace AArch64 |
| 55 | |
| 56 | namespace ARM64AS { |
| 57 | enum : unsigned { PTR32_SPTR = 270, PTR32_UPTR = 271, PTR64 = 272 }; |
| 58 | } |
| 59 | |
| 60 | class AArch64Subtarget; |
| 61 | |
| 62 | class AArch64TargetLowering : public TargetLowering { |
| 63 | public: |
| 64 | explicit AArch64TargetLowering(const TargetMachine &TM, |
| 65 | const AArch64Subtarget &STI); |
| 66 | |
| 67 | /// Control the following reassociation of operands: (op (op x, c1), y) -> (op |
| 68 | /// (op x, y), c1) where N0 is (op x, c1) and N1 is y. |
| 69 | bool isReassocProfitable(SelectionDAG &DAG, SDValue N0, |
| 70 | SDValue N1) const override; |
| 71 | |
| 72 | /// Selects the correct CCAssignFn for a given CallingConvention value. |
| 73 | CCAssignFn *CCAssignFnForCall(CallingConv::ID CC, bool IsVarArg) const; |
| 74 | |
| 75 | /// Selects the correct CCAssignFn for a given CallingConvention value. |
| 76 | CCAssignFn *CCAssignFnForReturn(CallingConv::ID CC) const; |
| 77 | |
| 78 | /// Determine which of the bits specified in Mask are known to be either zero |
| 79 | /// or one and return them in the KnownZero/KnownOne bitsets. |
| 80 | void computeKnownBitsForTargetNode(const SDValue Op, KnownBits &Known, |
| 81 | const APInt &DemandedElts, |
| 82 | const SelectionDAG &DAG, |
| 83 | unsigned Depth = 0) const override; |
| 84 | |
| 85 | unsigned ComputeNumSignBitsForTargetNode(SDValue Op, |
| 86 | const APInt &DemandedElts, |
| 87 | const SelectionDAG &DAG, |
| 88 | unsigned Depth) const override; |
| 89 | |
| 90 | MVT getPointerTy(const DataLayout &DL, uint32_t AS = 0) const override { |
| 91 | if ((AS == ARM64AS::PTR32_SPTR) || (AS == ARM64AS::PTR32_UPTR)) { |
| 92 | // These are 32-bit pointers created using the `__ptr32` extension or |
| 93 | // similar. They are handled by marking them as being in a different |
| 94 | // address space, and will be extended to 64-bits when used as the target |
| 95 | // of a load or store operation, or cast to a 64-bit pointer type. |
| 96 | return MVT::i32; |
| 97 | } else { |
| 98 | // Returning i64 unconditionally here (i.e. even for ILP32) means that the |
| 99 | // *DAG* representation of pointers will always be 64-bits. They will be |
| 100 | // truncated and extended when transferred to memory, but the 64-bit DAG |
| 101 | // allows us to use AArch64's addressing modes much more easily. |
| 102 | return MVT::i64; |
| 103 | } |
| 104 | } |
| 105 | |
| 106 | unsigned getVectorIdxWidth(const DataLayout &DL) const override { |
| 107 | // The VectorIdx type is i64, with both normal and ilp32. |
| 108 | return 64; |
| 109 | } |
| 110 | |
| 111 | bool targetShrinkDemandedConstant(SDValue Op, const APInt &DemandedBits, |
| 112 | const APInt &DemandedElts, |
| 113 | TargetLoweringOpt &TLO) const override; |
| 114 | |
| 115 | MVT getScalarShiftAmountTy(const DataLayout &DL, EVT) const override; |
| 116 | |
| 117 | /// Returns true if the target allows unaligned memory accesses of the |
| 118 | /// specified type. |
| 119 | bool allowsMisalignedMemoryAccesses( |
| 120 | EVT VT, unsigned AddrSpace = 0, Align Alignment = Align(1), |
| 121 | MachineMemOperand::Flags Flags = MachineMemOperand::MONone, |
| 122 | unsigned *Fast = nullptr) const override; |
| 123 | /// LLT variant. |
| 124 | bool allowsMisalignedMemoryAccesses(LLT Ty, unsigned AddrSpace, |
| 125 | Align Alignment, |
| 126 | MachineMemOperand::Flags Flags, |
| 127 | unsigned *Fast = nullptr) const override; |
| 128 | |
| 129 | /// Provide custom lowering hooks for some operations. |
| 130 | SDValue LowerOperation(SDValue Op, SelectionDAG &DAG) const override; |
| 131 | |
| 132 | SDValue PerformDAGCombine(SDNode *N, DAGCombinerInfo &DCI) const override; |
| 133 | |
| 134 | /// This method returns a target specific FastISel object, or null if the |
| 135 | /// target does not support "fast" ISel. |
| 136 | FastISel *createFastISel(FunctionLoweringInfo &funcInfo, |
| 137 | const TargetLibraryInfo *libInfo) const override; |
| 138 | |
| 139 | bool isOffsetFoldingLegal(const GlobalAddressSDNode *GA) const override; |
| 140 | |
| 141 | bool isFPImmLegal(const APFloat &Imm, EVT VT, |
| 142 | bool ForCodeSize) const override; |
| 143 | |
| 144 | /// Return true if the given shuffle mask can be codegen'd directly, or if it |
| 145 | /// should be stack expanded. |
| 146 | bool isShuffleMaskLegal(ArrayRef<int> M, EVT VT) const override; |
| 147 | |
| 148 | /// Similar to isShuffleMaskLegal. Return true is the given 'select with zero' |
| 149 | /// shuffle mask can be codegen'd directly. |
| 150 | bool isVectorClearMaskLegal(ArrayRef<int> M, EVT VT) const override; |
| 151 | |
| 152 | /// Return the ISD::SETCC ValueType. |
| 153 | EVT getSetCCResultType(const DataLayout &DL, LLVMContext &Context, |
| 154 | EVT VT) const override; |
| 155 | |
| 156 | SDValue ReconstructShuffle(SDValue Op, SelectionDAG &DAG) const; |
| 157 | |
| 158 | MachineBasicBlock *EmitF128CSEL(MachineInstr &MI, |
| 159 | MachineBasicBlock *BB) const; |
| 160 | |
| 161 | MachineBasicBlock *EmitLoweredCatchRet(MachineInstr &MI, |
| 162 | MachineBasicBlock *BB) const; |
| 163 | |
| 164 | MachineBasicBlock *EmitDynamicProbedAlloc(MachineInstr &MI, |
| 165 | MachineBasicBlock *MBB) const; |
| 166 | |
| 167 | MachineBasicBlock *EmitTileLoad(unsigned Opc, unsigned BaseReg, |
| 168 | MachineInstr &MI, |
| 169 | MachineBasicBlock *BB) const; |
| 170 | MachineBasicBlock *EmitFill(MachineInstr &MI, MachineBasicBlock *BB) const; |
| 171 | MachineBasicBlock *EmitZAInstr(unsigned Opc, unsigned BaseReg, |
| 172 | MachineInstr &MI, MachineBasicBlock *BB) const; |
| 173 | MachineBasicBlock *EmitZTInstr(MachineInstr &MI, MachineBasicBlock *BB, |
| 174 | unsigned Opcode, bool Op0IsDef) const; |
| 175 | MachineBasicBlock *EmitZero(MachineInstr &MI, MachineBasicBlock *BB) const; |
| 176 | MachineBasicBlock *EmitInitTPIDR2Object(MachineInstr &MI, |
| 177 | MachineBasicBlock *BB) const; |
| 178 | MachineBasicBlock *EmitAllocateZABuffer(MachineInstr &MI, |
| 179 | MachineBasicBlock *BB) const; |
| 180 | MachineBasicBlock *EmitAllocateSMESaveBuffer(MachineInstr &MI, |
| 181 | MachineBasicBlock *BB) const; |
| 182 | MachineBasicBlock *EmitGetSMESaveSize(MachineInstr &MI, |
| 183 | MachineBasicBlock *BB) const; |
| 184 | |
| 185 | MachineBasicBlock * |
| 186 | EmitInstrWithCustomInserter(MachineInstr &MI, |
| 187 | MachineBasicBlock *MBB) const override; |
| 188 | |
| 189 | bool getTgtMemIntrinsic(IntrinsicInfo &Info, const CallInst &I, |
| 190 | MachineFunction &MF, |
| 191 | unsigned Intrinsic) const override; |
| 192 | |
| 193 | bool shouldReduceLoadWidth(SDNode *Load, ISD::LoadExtType ExtTy, EVT NewVT, |
| 194 | std::optional<unsigned> ByteOffset) const override; |
| 195 | |
| 196 | bool shouldRemoveRedundantExtend(SDValue Op) const override; |
| 197 | |
| 198 | bool isTruncateFree(Type *Ty1, Type *Ty2) const override; |
| 199 | bool isTruncateFree(EVT VT1, EVT VT2) const override; |
| 200 | |
| 201 | bool isProfitableToHoist(Instruction *I) const override; |
| 202 | |
| 203 | bool isZExtFree(Type *Ty1, Type *Ty2) const override; |
| 204 | bool isZExtFree(EVT VT1, EVT VT2) const override; |
| 205 | bool isZExtFree(SDValue Val, EVT VT2) const override; |
| 206 | |
| 207 | bool optimizeExtendOrTruncateConversion( |
| 208 | Instruction *I, Loop *L, const TargetTransformInfo &TTI) const override; |
| 209 | |
| 210 | bool hasPairedLoad(EVT LoadedType, Align &RequiredAlignment) const override; |
| 211 | |
| 212 | unsigned getMaxSupportedInterleaveFactor() const override { return 4; } |
| 213 | |
| 214 | bool lowerInterleavedLoad(LoadInst *LI, |
| 215 | ArrayRef<ShuffleVectorInst *> Shuffles, |
| 216 | ArrayRef<unsigned> Indices, |
| 217 | unsigned Factor) const override; |
| 218 | bool lowerInterleavedStore(StoreInst *SI, ShuffleVectorInst *SVI, |
| 219 | unsigned Factor) const override; |
| 220 | |
| 221 | bool lowerDeinterleaveIntrinsicToLoad( |
| 222 | LoadInst *LI, ArrayRef<Value *> DeinterleaveValues) const override; |
| 223 | |
| 224 | bool lowerInterleaveIntrinsicToStore( |
| 225 | StoreInst *SI, ArrayRef<Value *> InterleaveValues) const override; |
| 226 | |
| 227 | bool isLegalAddImmediate(int64_t) const override; |
| 228 | bool isLegalAddScalableImmediate(int64_t) const override; |
| 229 | bool isLegalICmpImmediate(int64_t) const override; |
| 230 | |
| 231 | bool isMulAddWithConstProfitable(SDValue AddNode, |
| 232 | SDValue ConstNode) const override; |
| 233 | |
| 234 | bool shouldConsiderGEPOffsetSplit() const override; |
| 235 | |
| 236 | EVT getOptimalMemOpType(const MemOp &Op, |
| 237 | const AttributeList &FuncAttributes) const override; |
| 238 | |
| 239 | LLT getOptimalMemOpLLT(const MemOp &Op, |
| 240 | const AttributeList &FuncAttributes) const override; |
| 241 | |
| 242 | /// Return true if the addressing mode represented by AM is legal for this |
| 243 | /// target, for a load/store of the specified type. |
| 244 | bool isLegalAddressingMode(const DataLayout &DL, const AddrMode &AM, Type *Ty, |
| 245 | unsigned AS, |
| 246 | Instruction *I = nullptr) const override; |
| 247 | |
| 248 | int64_t getPreferredLargeGEPBaseOffset(int64_t MinOffset, |
| 249 | int64_t MaxOffset) const override; |
| 250 | |
| 251 | /// Return true if an FMA operation is faster than a pair of fmul and fadd |
| 252 | /// instructions. fmuladd intrinsics will be expanded to FMAs when this method |
| 253 | /// returns true, otherwise fmuladd is expanded to fmul + fadd. |
| 254 | bool isFMAFasterThanFMulAndFAdd(const MachineFunction &MF, |
| 255 | EVT VT) const override; |
| 256 | bool isFMAFasterThanFMulAndFAdd(const Function &F, Type *Ty) const override; |
| 257 | |
| 258 | bool generateFMAsInMachineCombiner(EVT VT, |
| 259 | CodeGenOptLevel OptLevel) const override; |
| 260 | |
| 261 | /// Return true if the target has native support for |
| 262 | /// the specified value type and it is 'desirable' to use the type for the |
| 263 | /// given node type. |
| 264 | bool isTypeDesirableForOp(unsigned Opc, EVT VT) const override; |
| 265 | |
| 266 | const MCPhysReg *getScratchRegisters(CallingConv::ID CC) const override; |
| 267 | ArrayRef<MCPhysReg> getRoundingControlRegisters() const override; |
| 268 | |
| 269 | /// Returns false if N is a bit extraction pattern of (X >> C) & Mask. |
| 270 | bool isDesirableToCommuteWithShift(const SDNode *N, |
| 271 | CombineLevel Level) const override; |
| 272 | |
| 273 | bool isDesirableToPullExtFromShl(const MachineInstr &MI) const override { |
| 274 | return false; |
| 275 | } |
| 276 | |
| 277 | /// Returns false if N is a bit extraction pattern of (X >> C) & Mask. |
| 278 | bool isDesirableToCommuteXorWithShift(const SDNode *N) const override; |
| 279 | |
| 280 | /// Return true if it is profitable to fold a pair of shifts into a mask. |
| 281 | bool shouldFoldConstantShiftPairToMask(const SDNode *N, |
| 282 | CombineLevel Level) const override; |
| 283 | |
| 284 | bool shouldFoldSelectWithIdentityConstant(unsigned BinOpcode, EVT VT, |
| 285 | unsigned SelectOpcode, SDValue X, |
| 286 | SDValue Y) const override; |
| 287 | |
| 288 | /// Returns true if it is beneficial to convert a load of a constant |
| 289 | /// to just the constant itself. |
| 290 | bool shouldConvertConstantLoadToIntImm(const APInt &Imm, |
| 291 | Type *Ty) const override; |
| 292 | |
| 293 | /// Return true if EXTRACT_SUBVECTOR is cheap for this result type |
| 294 | /// with this index. |
| 295 | bool (EVT ResVT, EVT SrcVT, |
| 296 | unsigned Index) const override; |
| 297 | |
| 298 | bool shouldFormOverflowOp(unsigned Opcode, EVT VT, |
| 299 | bool MathUsed) const override { |
| 300 | // Using overflow ops for overflow checks only should beneficial on |
| 301 | // AArch64. |
| 302 | return TargetLowering::shouldFormOverflowOp(Opcode, VT, MathUsed: true); |
| 303 | } |
| 304 | |
| 305 | Value *emitLoadLinked(IRBuilderBase &Builder, Type *ValueTy, Value *Addr, |
| 306 | AtomicOrdering Ord) const override; |
| 307 | Value *emitStoreConditional(IRBuilderBase &Builder, Value *Val, Value *Addr, |
| 308 | AtomicOrdering Ord) const override; |
| 309 | |
| 310 | void emitAtomicCmpXchgNoStoreLLBalance(IRBuilderBase &Builder) const override; |
| 311 | |
| 312 | bool isOpSuitableForLDPSTP(const Instruction *I) const; |
| 313 | bool isOpSuitableForLSE128(const Instruction *I) const; |
| 314 | bool isOpSuitableForRCPC3(const Instruction *I) const; |
| 315 | bool shouldInsertFencesForAtomic(const Instruction *I) const override; |
| 316 | bool |
| 317 | shouldInsertTrailingFenceForAtomicStore(const Instruction *I) const override; |
| 318 | |
| 319 | TargetLoweringBase::AtomicExpansionKind |
| 320 | shouldExpandAtomicLoadInIR(LoadInst *LI) const override; |
| 321 | TargetLoweringBase::AtomicExpansionKind |
| 322 | shouldExpandAtomicStoreInIR(StoreInst *SI) const override; |
| 323 | TargetLoweringBase::AtomicExpansionKind |
| 324 | shouldExpandAtomicRMWInIR(AtomicRMWInst *AI) const override; |
| 325 | |
| 326 | TargetLoweringBase::AtomicExpansionKind |
| 327 | shouldExpandAtomicCmpXchgInIR(AtomicCmpXchgInst *AI) const override; |
| 328 | |
| 329 | bool useLoadStackGuardNode(const Module &M) const override; |
| 330 | TargetLoweringBase::LegalizeTypeAction |
| 331 | getPreferredVectorAction(MVT VT) const override; |
| 332 | |
| 333 | /// If the target has a standard location for the stack protector cookie, |
| 334 | /// returns the address of that location. Otherwise, returns nullptr. |
| 335 | Value *getIRStackGuard(IRBuilderBase &IRB) const override; |
| 336 | |
| 337 | void insertSSPDeclarations(Module &M) const override; |
| 338 | Value *getSDagStackGuard(const Module &M) const override; |
| 339 | Function *getSSPStackGuardCheck(const Module &M) const override; |
| 340 | |
| 341 | /// If the target has a standard location for the unsafe stack pointer, |
| 342 | /// returns the address of that location. Otherwise, returns nullptr. |
| 343 | Value *getSafeStackPointerLocation(IRBuilderBase &IRB) const override; |
| 344 | |
| 345 | /// If a physical register, this returns the register that receives the |
| 346 | /// exception address on entry to an EH pad. |
| 347 | Register |
| 348 | getExceptionPointerRegister(const Constant *PersonalityFn) const override; |
| 349 | |
| 350 | /// If a physical register, this returns the register that receives the |
| 351 | /// exception typeid on entry to a landing pad. |
| 352 | Register |
| 353 | getExceptionSelectorRegister(const Constant *PersonalityFn) const override; |
| 354 | |
| 355 | bool isIntDivCheap(EVT VT, AttributeList Attr) const override; |
| 356 | |
| 357 | bool canMergeStoresTo(unsigned AddressSpace, EVT MemVT, |
| 358 | const MachineFunction &MF) const override; |
| 359 | |
| 360 | bool isCheapToSpeculateCttz(Type *) const override { |
| 361 | return true; |
| 362 | } |
| 363 | |
| 364 | bool isCheapToSpeculateCtlz(Type *) const override { |
| 365 | return true; |
| 366 | } |
| 367 | |
| 368 | bool isMaskAndCmp0FoldingBeneficial(const Instruction &AndI) const override; |
| 369 | |
| 370 | bool hasAndNotCompare(SDValue V) const override { |
| 371 | // We can use bics for any scalar. |
| 372 | return V.getValueType().isScalarInteger(); |
| 373 | } |
| 374 | |
| 375 | bool hasAndNot(SDValue Y) const override { |
| 376 | EVT VT = Y.getValueType(); |
| 377 | |
| 378 | if (!VT.isVector()) |
| 379 | return hasAndNotCompare(V: Y); |
| 380 | |
| 381 | if (VT.isScalableVector()) |
| 382 | return true; |
| 383 | |
| 384 | return VT.getFixedSizeInBits() >= 64; // vector 'bic' |
| 385 | } |
| 386 | |
| 387 | bool shouldProduceAndByConstByHoistingConstFromShiftsLHSOfAnd( |
| 388 | SDValue X, ConstantSDNode *XC, ConstantSDNode *CC, SDValue Y, |
| 389 | unsigned OldShiftOpcode, unsigned NewShiftOpcode, |
| 390 | SelectionDAG &DAG) const override; |
| 391 | |
| 392 | ShiftLegalizationStrategy |
| 393 | preferredShiftLegalizationStrategy(SelectionDAG &DAG, SDNode *N, |
| 394 | unsigned ExpansionFactor) const override; |
| 395 | |
| 396 | bool shouldTransformSignedTruncationCheck(EVT XVT, |
| 397 | unsigned KeptBits) const override { |
| 398 | // For vectors, we don't have a preference.. |
| 399 | if (XVT.isVector()) |
| 400 | return false; |
| 401 | |
| 402 | auto VTIsOk = [](EVT VT) -> bool { |
| 403 | return VT == MVT::i8 || VT == MVT::i16 || VT == MVT::i32 || |
| 404 | VT == MVT::i64; |
| 405 | }; |
| 406 | |
| 407 | // We are ok with KeptBitsVT being byte/word/dword, what SXT supports. |
| 408 | // XVT will be larger than KeptBitsVT. |
| 409 | MVT KeptBitsVT = MVT::getIntegerVT(BitWidth: KeptBits); |
| 410 | return VTIsOk(XVT) && VTIsOk(KeptBitsVT); |
| 411 | } |
| 412 | |
| 413 | bool preferIncOfAddToSubOfNot(EVT VT) const override; |
| 414 | |
| 415 | bool shouldConvertFpToSat(unsigned Op, EVT FPVT, EVT VT) const override; |
| 416 | |
| 417 | bool shouldExpandCmpUsingSelects(EVT VT) const override; |
| 418 | |
| 419 | bool isComplexDeinterleavingSupported() const override; |
| 420 | bool isComplexDeinterleavingOperationSupported( |
| 421 | ComplexDeinterleavingOperation Operation, Type *Ty) const override; |
| 422 | |
| 423 | Value *createComplexDeinterleavingIR( |
| 424 | IRBuilderBase &B, ComplexDeinterleavingOperation OperationType, |
| 425 | ComplexDeinterleavingRotation Rotation, Value *InputA, Value *InputB, |
| 426 | Value *Accumulator = nullptr) const override; |
| 427 | |
| 428 | bool supportSplitCSR(MachineFunction *MF) const override { |
| 429 | return MF->getFunction().getCallingConv() == CallingConv::CXX_FAST_TLS && |
| 430 | MF->getFunction().hasFnAttribute(Kind: Attribute::NoUnwind); |
| 431 | } |
| 432 | void initializeSplitCSR(MachineBasicBlock *Entry) const override; |
| 433 | void insertCopiesSplitCSR( |
| 434 | MachineBasicBlock *Entry, |
| 435 | const SmallVectorImpl<MachineBasicBlock *> &Exits) const override; |
| 436 | |
| 437 | bool supportSwiftError() const override { |
| 438 | return true; |
| 439 | } |
| 440 | |
| 441 | bool supportPtrAuthBundles() const override { return true; } |
| 442 | |
| 443 | bool supportKCFIBundles() const override { return true; } |
| 444 | |
| 445 | MachineInstr *EmitKCFICheck(MachineBasicBlock &MBB, |
| 446 | MachineBasicBlock::instr_iterator &MBBI, |
| 447 | const TargetInstrInfo *TII) const override; |
| 448 | |
| 449 | /// Enable aggressive FMA fusion on targets that want it. |
| 450 | bool enableAggressiveFMAFusion(EVT VT) const override; |
| 451 | |
| 452 | bool aggressivelyPreferBuildVectorSources(EVT VecVT) const override { |
| 453 | return true; |
| 454 | } |
| 455 | |
| 456 | /// Returns the size of the platform's va_list object. |
| 457 | unsigned getVaListSizeInBits(const DataLayout &DL) const override; |
| 458 | |
| 459 | /// Returns true if \p VecTy is a legal interleaved access type. This |
| 460 | /// function checks the vector element type and the overall width of the |
| 461 | /// vector. |
| 462 | bool isLegalInterleavedAccessType(VectorType *VecTy, const DataLayout &DL, |
| 463 | bool &UseScalable) const; |
| 464 | |
| 465 | /// Returns the number of interleaved accesses that will be generated when |
| 466 | /// lowering accesses of the given type. |
| 467 | unsigned getNumInterleavedAccesses(VectorType *VecTy, const DataLayout &DL, |
| 468 | bool UseScalable) const; |
| 469 | |
| 470 | MachineMemOperand::Flags getTargetMMOFlags( |
| 471 | const Instruction &I) const override; |
| 472 | |
| 473 | bool functionArgumentNeedsConsecutiveRegisters( |
| 474 | Type *Ty, CallingConv::ID CallConv, bool isVarArg, |
| 475 | const DataLayout &DL) const override; |
| 476 | |
| 477 | /// Used for exception handling on Win64. |
| 478 | bool needsFixedCatchObjects() const override; |
| 479 | |
| 480 | bool fallBackToDAGISel(const Instruction &Inst) const override; |
| 481 | |
| 482 | /// SVE code generation for fixed length vectors does not custom lower |
| 483 | /// BUILD_VECTOR. This makes BUILD_VECTOR legalisation a source of stores to |
| 484 | /// merge. However, merging them creates a BUILD_VECTOR that is just as |
| 485 | /// illegal as the original, thus leading to an infinite legalisation loop. |
| 486 | /// NOTE: Once BUILD_VECTOR is legal or can be custom lowered for all legal |
| 487 | /// vector types this override can be removed. |
| 488 | bool mergeStoresAfterLegalization(EVT VT) const override; |
| 489 | |
| 490 | // If the platform/function should have a redzone, return the size in bytes. |
| 491 | unsigned getRedZoneSize(const Function &F) const { |
| 492 | if (F.hasFnAttribute(Kind: Attribute::NoRedZone)) |
| 493 | return 0; |
| 494 | return 128; |
| 495 | } |
| 496 | |
| 497 | bool isAllActivePredicate(SelectionDAG &DAG, SDValue N) const; |
| 498 | EVT getPromotedVTForPredicate(EVT VT) const; |
| 499 | |
| 500 | EVT getAsmOperandValueType(const DataLayout &DL, Type *Ty, |
| 501 | bool AllowUnknown = false) const override; |
| 502 | |
| 503 | bool shouldExpandGetActiveLaneMask(EVT VT, EVT OpVT) const override; |
| 504 | |
| 505 | bool |
| 506 | shouldExpandPartialReductionIntrinsic(const IntrinsicInst *I) const override; |
| 507 | |
| 508 | bool shouldExpandCttzElements(EVT VT) const override; |
| 509 | |
| 510 | bool shouldExpandVectorMatch(EVT VT, unsigned SearchSize) const override; |
| 511 | |
| 512 | /// If a change in streaming mode is required on entry to/return from a |
| 513 | /// function call it emits and returns the corresponding SMSTART or SMSTOP |
| 514 | /// node. \p Condition should be one of the enum values from |
| 515 | /// AArch64SME::ToggleCondition. |
| 516 | SDValue changeStreamingMode(SelectionDAG &DAG, SDLoc DL, bool Enable, |
| 517 | SDValue Chain, SDValue InGlue, unsigned Condition, |
| 518 | SDValue PStateSM = SDValue()) const; |
| 519 | |
| 520 | bool isVScaleKnownToBeAPowerOfTwo() const override { return true; } |
| 521 | |
| 522 | // Normally SVE is only used for byte size vectors that do not fit within a |
| 523 | // NEON vector. This changes when OverrideNEON is true, allowing SVE to be |
| 524 | // used for 64bit and 128bit vectors as well. |
| 525 | bool useSVEForFixedLengthVectorVT(EVT VT, bool OverrideNEON = false) const; |
| 526 | |
| 527 | // Follow NEON ABI rules even when using SVE for fixed length vectors. |
| 528 | MVT getRegisterTypeForCallingConv(LLVMContext &Context, CallingConv::ID CC, |
| 529 | EVT VT) const override; |
| 530 | unsigned getNumRegistersForCallingConv(LLVMContext &Context, |
| 531 | CallingConv::ID CC, |
| 532 | EVT VT) const override; |
| 533 | unsigned getVectorTypeBreakdownForCallingConv(LLVMContext &Context, |
| 534 | CallingConv::ID CC, EVT VT, |
| 535 | EVT &IntermediateVT, |
| 536 | unsigned &NumIntermediates, |
| 537 | MVT &RegisterVT) const override; |
| 538 | |
| 539 | /// True if stack clash protection is enabled for this functions. |
| 540 | bool hasInlineStackProbe(const MachineFunction &MF) const override; |
| 541 | |
| 542 | /// In AArch64, true if FEAT_CPA is present. Allows pointer arithmetic |
| 543 | /// semantics to be preserved for instruction selection. |
| 544 | bool shouldPreservePtrArith(const Function &F, EVT PtrVT) const override; |
| 545 | |
| 546 | private: |
| 547 | /// Keep a pointer to the AArch64Subtarget around so that we can |
| 548 | /// make the right decision when generating code for different targets. |
| 549 | const AArch64Subtarget *Subtarget; |
| 550 | |
| 551 | bool isExtFreeImpl(const Instruction *Ext) const override; |
| 552 | |
| 553 | void addTypeForNEON(MVT VT); |
| 554 | void addTypeForFixedLengthSVE(MVT VT); |
| 555 | void addDRType(MVT VT); |
| 556 | void addQRType(MVT VT); |
| 557 | |
| 558 | bool shouldExpandBuildVectorWithShuffles(EVT, unsigned) const override; |
| 559 | |
| 560 | SDValue LowerFormalArguments(SDValue Chain, CallingConv::ID CallConv, |
| 561 | bool isVarArg, |
| 562 | const SmallVectorImpl<ISD::InputArg> &Ins, |
| 563 | const SDLoc &DL, SelectionDAG &DAG, |
| 564 | SmallVectorImpl<SDValue> &InVals) const override; |
| 565 | |
| 566 | void AdjustInstrPostInstrSelection(MachineInstr &MI, |
| 567 | SDNode *Node) const override; |
| 568 | |
| 569 | SDValue LowerCall(CallLoweringInfo & /*CLI*/, |
| 570 | SmallVectorImpl<SDValue> &InVals) const override; |
| 571 | |
| 572 | SDValue LowerCallResult(SDValue Chain, SDValue InGlue, |
| 573 | CallingConv::ID CallConv, bool isVarArg, |
| 574 | const SmallVectorImpl<CCValAssign> &RVLocs, |
| 575 | const SDLoc &DL, SelectionDAG &DAG, |
| 576 | SmallVectorImpl<SDValue> &InVals, bool isThisReturn, |
| 577 | SDValue ThisVal, bool RequiresSMChange) const; |
| 578 | |
| 579 | SDValue LowerLOAD(SDValue Op, SelectionDAG &DAG) const; |
| 580 | SDValue LowerSTORE(SDValue Op, SelectionDAG &DAG) const; |
| 581 | SDValue LowerStore128(SDValue Op, SelectionDAG &DAG) const; |
| 582 | SDValue LowerABS(SDValue Op, SelectionDAG &DAG) const; |
| 583 | |
| 584 | SDValue LowerMGATHER(SDValue Op, SelectionDAG &DAG) const; |
| 585 | SDValue LowerMSCATTER(SDValue Op, SelectionDAG &DAG) const; |
| 586 | |
| 587 | SDValue LowerMLOAD(SDValue Op, SelectionDAG &DAG) const; |
| 588 | |
| 589 | SDValue LowerVECTOR_COMPRESS(SDValue Op, SelectionDAG &DAG) const; |
| 590 | |
| 591 | SDValue LowerINTRINSIC_W_CHAIN(SDValue Op, SelectionDAG &DAG) const; |
| 592 | SDValue LowerINTRINSIC_WO_CHAIN(SDValue Op, SelectionDAG &DAG) const; |
| 593 | SDValue LowerINTRINSIC_VOID(SDValue Op, SelectionDAG &DAG) const; |
| 594 | |
| 595 | bool |
| 596 | isEligibleForTailCallOptimization(const CallLoweringInfo &CLI) const; |
| 597 | |
| 598 | /// Finds the incoming stack arguments which overlap the given fixed stack |
| 599 | /// object and incorporates their load into the current chain. This prevents |
| 600 | /// an upcoming store from clobbering the stack argument before it's used. |
| 601 | SDValue addTokenForArgument(SDValue Chain, SelectionDAG &DAG, |
| 602 | MachineFrameInfo &MFI, int ClobberedFI) const; |
| 603 | |
| 604 | bool DoesCalleeRestoreStack(CallingConv::ID CallCC, bool TailCallOpt) const; |
| 605 | |
| 606 | void saveVarArgRegisters(CCState &CCInfo, SelectionDAG &DAG, const SDLoc &DL, |
| 607 | SDValue &Chain) const; |
| 608 | |
| 609 | bool CanLowerReturn(CallingConv::ID CallConv, MachineFunction &MF, |
| 610 | bool isVarArg, |
| 611 | const SmallVectorImpl<ISD::OutputArg> &Outs, |
| 612 | LLVMContext &Context, const Type *RetTy) const override; |
| 613 | |
| 614 | SDValue LowerReturn(SDValue Chain, CallingConv::ID CallConv, bool isVarArg, |
| 615 | const SmallVectorImpl<ISD::OutputArg> &Outs, |
| 616 | const SmallVectorImpl<SDValue> &OutVals, const SDLoc &DL, |
| 617 | SelectionDAG &DAG) const override; |
| 618 | |
| 619 | SDValue getTargetNode(GlobalAddressSDNode *N, EVT Ty, SelectionDAG &DAG, |
| 620 | unsigned Flag) const; |
| 621 | SDValue getTargetNode(JumpTableSDNode *N, EVT Ty, SelectionDAG &DAG, |
| 622 | unsigned Flag) const; |
| 623 | SDValue getTargetNode(ConstantPoolSDNode *N, EVT Ty, SelectionDAG &DAG, |
| 624 | unsigned Flag) const; |
| 625 | SDValue getTargetNode(BlockAddressSDNode *N, EVT Ty, SelectionDAG &DAG, |
| 626 | unsigned Flag) const; |
| 627 | SDValue getTargetNode(ExternalSymbolSDNode *N, EVT Ty, SelectionDAG &DAG, |
| 628 | unsigned Flag) const; |
| 629 | template <class NodeTy> |
| 630 | SDValue getGOT(NodeTy *N, SelectionDAG &DAG, unsigned Flags = 0) const; |
| 631 | template <class NodeTy> |
| 632 | SDValue getAddrLarge(NodeTy *N, SelectionDAG &DAG, unsigned Flags = 0) const; |
| 633 | template <class NodeTy> |
| 634 | SDValue getAddr(NodeTy *N, SelectionDAG &DAG, unsigned Flags = 0) const; |
| 635 | template <class NodeTy> |
| 636 | SDValue getAddrTiny(NodeTy *N, SelectionDAG &DAG, unsigned Flags = 0) const; |
| 637 | SDValue LowerADDROFRETURNADDR(SDValue Op, SelectionDAG &DAG) const; |
| 638 | SDValue LowerGlobalAddress(SDValue Op, SelectionDAG &DAG) const; |
| 639 | SDValue LowerGlobalTLSAddress(SDValue Op, SelectionDAG &DAG) const; |
| 640 | SDValue LowerDarwinGlobalTLSAddress(SDValue Op, SelectionDAG &DAG) const; |
| 641 | SDValue LowerELFGlobalTLSAddress(SDValue Op, SelectionDAG &DAG) const; |
| 642 | SDValue LowerELFTLSLocalExec(const GlobalValue *GV, SDValue ThreadBase, |
| 643 | const SDLoc &DL, SelectionDAG &DAG) const; |
| 644 | SDValue LowerELFTLSDescCallSeq(SDValue SymAddr, const SDLoc &DL, |
| 645 | SelectionDAG &DAG) const; |
| 646 | SDValue LowerWindowsGlobalTLSAddress(SDValue Op, SelectionDAG &DAG) const; |
| 647 | SDValue LowerPtrAuthGlobalAddress(SDValue Op, SelectionDAG &DAG) const; |
| 648 | SDValue LowerSETCC(SDValue Op, SelectionDAG &DAG) const; |
| 649 | SDValue LowerSETCCCARRY(SDValue Op, SelectionDAG &DAG) const; |
| 650 | SDValue LowerBR_CC(SDValue Op, SelectionDAG &DAG) const; |
| 651 | SDValue LowerSELECT(SDValue Op, SelectionDAG &DAG) const; |
| 652 | SDValue LowerSELECT_CC(SDValue Op, SelectionDAG &DAG) const; |
| 653 | SDValue LowerSELECT_CC(ISD::CondCode CC, SDValue LHS, SDValue RHS, |
| 654 | SDValue TVal, SDValue FVal, |
| 655 | iterator_range<SDNode::user_iterator> Users, |
| 656 | bool HasNoNans, const SDLoc &dl, |
| 657 | SelectionDAG &DAG) const; |
| 658 | SDValue LowerINIT_TRAMPOLINE(SDValue Op, SelectionDAG &DAG) const; |
| 659 | SDValue LowerADJUST_TRAMPOLINE(SDValue Op, SelectionDAG &DAG) const; |
| 660 | SDValue LowerJumpTable(SDValue Op, SelectionDAG &DAG) const; |
| 661 | SDValue LowerBR_JT(SDValue Op, SelectionDAG &DAG) const; |
| 662 | SDValue LowerBRIND(SDValue Op, SelectionDAG &DAG) const; |
| 663 | SDValue LowerConstantPool(SDValue Op, SelectionDAG &DAG) const; |
| 664 | SDValue LowerBlockAddress(SDValue Op, SelectionDAG &DAG) const; |
| 665 | SDValue LowerAAPCS_VASTART(SDValue Op, SelectionDAG &DAG) const; |
| 666 | SDValue LowerDarwin_VASTART(SDValue Op, SelectionDAG &DAG) const; |
| 667 | SDValue LowerWin64_VASTART(SDValue Op, SelectionDAG &DAG) const; |
| 668 | SDValue LowerVASTART(SDValue Op, SelectionDAG &DAG) const; |
| 669 | SDValue LowerVACOPY(SDValue Op, SelectionDAG &DAG) const; |
| 670 | SDValue LowerVAARG(SDValue Op, SelectionDAG &DAG) const; |
| 671 | SDValue LowerFRAMEADDR(SDValue Op, SelectionDAG &DAG) const; |
| 672 | SDValue LowerSPONENTRY(SDValue Op, SelectionDAG &DAG) const; |
| 673 | SDValue LowerRETURNADDR(SDValue Op, SelectionDAG &DAG) const; |
| 674 | SDValue LowerGET_ROUNDING(SDValue Op, SelectionDAG &DAG) const; |
| 675 | SDValue LowerSET_ROUNDING(SDValue Op, SelectionDAG &DAG) const; |
| 676 | SDValue LowerGET_FPMODE(SDValue Op, SelectionDAG &DAG) const; |
| 677 | SDValue LowerSET_FPMODE(SDValue Op, SelectionDAG &DAG) const; |
| 678 | SDValue LowerRESET_FPMODE(SDValue Op, SelectionDAG &DAG) const; |
| 679 | SDValue LowerINSERT_VECTOR_ELT(SDValue Op, SelectionDAG &DAG) const; |
| 680 | SDValue (SDValue Op, SelectionDAG &DAG) const; |
| 681 | SDValue LowerBUILD_VECTOR(SDValue Op, SelectionDAG &DAG) const; |
| 682 | SDValue LowerZERO_EXTEND_VECTOR_INREG(SDValue Op, SelectionDAG &DAG) const; |
| 683 | SDValue LowerVECTOR_SHUFFLE(SDValue Op, SelectionDAG &DAG) const; |
| 684 | SDValue LowerSPLAT_VECTOR(SDValue Op, SelectionDAG &DAG) const; |
| 685 | SDValue LowerDUPQLane(SDValue Op, SelectionDAG &DAG) const; |
| 686 | SDValue LowerToPredicatedOp(SDValue Op, SelectionDAG &DAG, |
| 687 | unsigned NewOp) const; |
| 688 | SDValue LowerToScalableOp(SDValue Op, SelectionDAG &DAG) const; |
| 689 | SDValue LowerVECTOR_SPLICE(SDValue Op, SelectionDAG &DAG) const; |
| 690 | SDValue (SDValue Op, SelectionDAG &DAG) const; |
| 691 | SDValue LowerINSERT_SUBVECTOR(SDValue Op, SelectionDAG &DAG) const; |
| 692 | SDValue LowerVECTOR_DEINTERLEAVE(SDValue Op, SelectionDAG &DAG) const; |
| 693 | SDValue LowerVECTOR_INTERLEAVE(SDValue Op, SelectionDAG &DAG) const; |
| 694 | SDValue LowerVECTOR_HISTOGRAM(SDValue Op, SelectionDAG &DAG) const; |
| 695 | SDValue LowerPARTIAL_REDUCE_MLA(SDValue Op, SelectionDAG &DAG) const; |
| 696 | SDValue LowerGET_ACTIVE_LANE_MASK(SDValue Op, SelectionDAG &DAG) const; |
| 697 | SDValue LowerDIV(SDValue Op, SelectionDAG &DAG) const; |
| 698 | SDValue LowerMUL(SDValue Op, SelectionDAG &DAG) const; |
| 699 | SDValue LowerVectorSRA_SRL_SHL(SDValue Op, SelectionDAG &DAG) const; |
| 700 | SDValue LowerShiftParts(SDValue Op, SelectionDAG &DAG) const; |
| 701 | SDValue LowerVSETCC(SDValue Op, SelectionDAG &DAG) const; |
| 702 | SDValue LowerCTPOP_PARITY(SDValue Op, SelectionDAG &DAG) const; |
| 703 | SDValue LowerCTTZ(SDValue Op, SelectionDAG &DAG) const; |
| 704 | SDValue LowerBitreverse(SDValue Op, SelectionDAG &DAG) const; |
| 705 | SDValue LowerMinMax(SDValue Op, SelectionDAG &DAG) const; |
| 706 | SDValue LowerFCOPYSIGN(SDValue Op, SelectionDAG &DAG) const; |
| 707 | SDValue LowerFP_EXTEND(SDValue Op, SelectionDAG &DAG) const; |
| 708 | SDValue LowerFP_ROUND(SDValue Op, SelectionDAG &DAG) const; |
| 709 | SDValue LowerVectorFP_TO_INT(SDValue Op, SelectionDAG &DAG) const; |
| 710 | SDValue LowerVectorFP_TO_INT_SAT(SDValue Op, SelectionDAG &DAG) const; |
| 711 | SDValue LowerFP_TO_INT(SDValue Op, SelectionDAG &DAG) const; |
| 712 | SDValue LowerFP_TO_INT_SAT(SDValue Op, SelectionDAG &DAG) const; |
| 713 | SDValue LowerVectorXRINT(SDValue Op, SelectionDAG &DAG) const; |
| 714 | SDValue LowerINT_TO_FP(SDValue Op, SelectionDAG &DAG) const; |
| 715 | SDValue LowerVectorINT_TO_FP(SDValue Op, SelectionDAG &DAG) const; |
| 716 | SDValue LowerVectorOR(SDValue Op, SelectionDAG &DAG) const; |
| 717 | SDValue LowerXOR(SDValue Op, SelectionDAG &DAG) const; |
| 718 | SDValue LowerCONCAT_VECTORS(SDValue Op, SelectionDAG &DAG) const; |
| 719 | SDValue LowerFSINCOS(SDValue Op, SelectionDAG &DAG) const; |
| 720 | SDValue LowerBITCAST(SDValue Op, SelectionDAG &DAG) const; |
| 721 | SDValue LowerVSCALE(SDValue Op, SelectionDAG &DAG) const; |
| 722 | SDValue LowerTRUNCATE(SDValue Op, SelectionDAG &DAG) const; |
| 723 | SDValue LowerVECREDUCE(SDValue Op, SelectionDAG &DAG) const; |
| 724 | SDValue LowerATOMIC_LOAD_AND(SDValue Op, SelectionDAG &DAG) const; |
| 725 | SDValue LowerWindowsDYNAMIC_STACKALLOC(SDValue Op, SelectionDAG &DAG) const; |
| 726 | SDValue LowerInlineDYNAMIC_STACKALLOC(SDValue Op, SelectionDAG &DAG) const; |
| 727 | SDValue LowerDYNAMIC_STACKALLOC(SDValue Op, SelectionDAG &DAG) const; |
| 728 | |
| 729 | SDValue LowerAVG(SDValue Op, SelectionDAG &DAG, unsigned NewOp) const; |
| 730 | |
| 731 | SDValue LowerFixedLengthVectorIntDivideToSVE(SDValue Op, |
| 732 | SelectionDAG &DAG) const; |
| 733 | SDValue LowerFixedLengthVectorIntExtendToSVE(SDValue Op, |
| 734 | SelectionDAG &DAG) const; |
| 735 | SDValue LowerFixedLengthVectorLoadToSVE(SDValue Op, SelectionDAG &DAG) const; |
| 736 | SDValue LowerFixedLengthVectorMLoadToSVE(SDValue Op, SelectionDAG &DAG) const; |
| 737 | SDValue LowerVECREDUCE_SEQ_FADD(SDValue ScalarOp, SelectionDAG &DAG) const; |
| 738 | SDValue LowerPredReductionToSVE(SDValue ScalarOp, SelectionDAG &DAG) const; |
| 739 | SDValue LowerReductionToSVE(unsigned Opcode, SDValue ScalarOp, |
| 740 | SelectionDAG &DAG) const; |
| 741 | SDValue LowerFixedLengthVectorSelectToSVE(SDValue Op, SelectionDAG &DAG) const; |
| 742 | SDValue LowerFixedLengthVectorSetccToSVE(SDValue Op, SelectionDAG &DAG) const; |
| 743 | SDValue LowerFixedLengthVectorStoreToSVE(SDValue Op, SelectionDAG &DAG) const; |
| 744 | SDValue LowerFixedLengthVectorMStoreToSVE(SDValue Op, |
| 745 | SelectionDAG &DAG) const; |
| 746 | SDValue LowerFixedLengthVectorTruncateToSVE(SDValue Op, |
| 747 | SelectionDAG &DAG) const; |
| 748 | SDValue (SDValue Op, SelectionDAG &DAG) const; |
| 749 | SDValue LowerFixedLengthInsertVectorElt(SDValue Op, SelectionDAG &DAG) const; |
| 750 | SDValue LowerFixedLengthBitcastToSVE(SDValue Op, SelectionDAG &DAG) const; |
| 751 | SDValue LowerFixedLengthConcatVectorsToSVE(SDValue Op, |
| 752 | SelectionDAG &DAG) const; |
| 753 | SDValue LowerFixedLengthFPExtendToSVE(SDValue Op, SelectionDAG &DAG) const; |
| 754 | SDValue LowerFixedLengthFPRoundToSVE(SDValue Op, SelectionDAG &DAG) const; |
| 755 | SDValue LowerFixedLengthIntToFPToSVE(SDValue Op, SelectionDAG &DAG) const; |
| 756 | SDValue LowerFixedLengthFPToIntToSVE(SDValue Op, SelectionDAG &DAG) const; |
| 757 | SDValue LowerFixedLengthVECTOR_SHUFFLEToSVE(SDValue Op, |
| 758 | SelectionDAG &DAG) const; |
| 759 | SDValue LowerFixedLengthBuildVectorToSVE(SDValue Op, SelectionDAG &DAG) const; |
| 760 | |
| 761 | SDValue BuildSDIVPow2(SDNode *N, const APInt &Divisor, SelectionDAG &DAG, |
| 762 | SmallVectorImpl<SDNode *> &Created) const override; |
| 763 | SDValue BuildSREMPow2(SDNode *N, const APInt &Divisor, SelectionDAG &DAG, |
| 764 | SmallVectorImpl<SDNode *> &Created) const override; |
| 765 | SDValue getSqrtEstimate(SDValue Operand, SelectionDAG &DAG, int Enabled, |
| 766 | int &, bool &UseOneConst, |
| 767 | bool Reciprocal) const override; |
| 768 | SDValue getRecipEstimate(SDValue Operand, SelectionDAG &DAG, int Enabled, |
| 769 | int &) const override; |
| 770 | SDValue getSqrtInputTest(SDValue Operand, SelectionDAG &DAG, |
| 771 | const DenormalMode &Mode) const override; |
| 772 | SDValue getSqrtResultForDenormInput(SDValue Operand, |
| 773 | SelectionDAG &DAG) const override; |
| 774 | unsigned combineRepeatedFPDivisors() const override; |
| 775 | |
| 776 | ConstraintType getConstraintType(StringRef Constraint) const override; |
| 777 | Register getRegisterByName(const char* RegName, LLT VT, |
| 778 | const MachineFunction &MF) const override; |
| 779 | |
| 780 | /// Examine constraint string and operand type and determine a weight value. |
| 781 | /// The operand object must already have been set up with the operand type. |
| 782 | ConstraintWeight |
| 783 | getSingleConstraintMatchWeight(AsmOperandInfo &info, |
| 784 | const char *constraint) const override; |
| 785 | |
| 786 | std::pair<unsigned, const TargetRegisterClass *> |
| 787 | getRegForInlineAsmConstraint(const TargetRegisterInfo *TRI, |
| 788 | StringRef Constraint, MVT VT) const override; |
| 789 | |
| 790 | const char *LowerXConstraint(EVT ConstraintVT) const override; |
| 791 | |
| 792 | void LowerAsmOperandForConstraint(SDValue Op, StringRef Constraint, |
| 793 | std::vector<SDValue> &Ops, |
| 794 | SelectionDAG &DAG) const override; |
| 795 | |
| 796 | InlineAsm::ConstraintCode |
| 797 | getInlineAsmMemConstraint(StringRef ConstraintCode) const override { |
| 798 | if (ConstraintCode == "Q" ) |
| 799 | return InlineAsm::ConstraintCode::Q; |
| 800 | // FIXME: clang has code for 'Ump', 'Utf', 'Usa', and 'Ush' but these are |
| 801 | // followed by llvm_unreachable so we'll leave them unimplemented in |
| 802 | // the backend for now. |
| 803 | return TargetLowering::getInlineAsmMemConstraint(ConstraintCode); |
| 804 | } |
| 805 | |
| 806 | /// Handle Lowering flag assembly outputs. |
| 807 | SDValue LowerAsmOutputForConstraint(SDValue &Chain, SDValue &Flag, |
| 808 | const SDLoc &DL, |
| 809 | const AsmOperandInfo &Constraint, |
| 810 | SelectionDAG &DAG) const override; |
| 811 | |
| 812 | bool shouldExtendGSIndex(EVT VT, EVT &EltTy) const override; |
| 813 | bool shouldRemoveExtendFromGSIndex(SDValue Extend, EVT DataVT) const override; |
| 814 | bool isVectorLoadExtDesirable(SDValue ExtVal) const override; |
| 815 | bool isUsedByReturnOnly(SDNode *N, SDValue &Chain) const override; |
| 816 | bool mayBeEmittedAsTailCall(const CallInst *CI) const override; |
| 817 | bool getIndexedAddressParts(SDNode *N, SDNode *Op, SDValue &Base, |
| 818 | SDValue &Offset, SelectionDAG &DAG) const; |
| 819 | bool getPreIndexedAddressParts(SDNode *N, SDValue &Base, SDValue &Offset, |
| 820 | ISD::MemIndexedMode &AM, |
| 821 | SelectionDAG &DAG) const override; |
| 822 | bool getPostIndexedAddressParts(SDNode *N, SDNode *Op, SDValue &Base, |
| 823 | SDValue &Offset, ISD::MemIndexedMode &AM, |
| 824 | SelectionDAG &DAG) const override; |
| 825 | bool isIndexingLegal(MachineInstr &MI, Register Base, Register Offset, |
| 826 | bool IsPre, MachineRegisterInfo &MRI) const override; |
| 827 | |
| 828 | void ReplaceNodeResults(SDNode *N, SmallVectorImpl<SDValue> &Results, |
| 829 | SelectionDAG &DAG) const override; |
| 830 | void ReplaceBITCASTResults(SDNode *N, SmallVectorImpl<SDValue> &Results, |
| 831 | SelectionDAG &DAG) const; |
| 832 | void (SDNode *N, |
| 833 | SmallVectorImpl<SDValue> &Results, |
| 834 | SelectionDAG &DAG) const; |
| 835 | void ReplaceGetActiveLaneMaskResults(SDNode *N, |
| 836 | SmallVectorImpl<SDValue> &Results, |
| 837 | SelectionDAG &DAG) const; |
| 838 | |
| 839 | bool shouldNormalizeToSelectSequence(LLVMContext &, EVT) const override; |
| 840 | |
| 841 | void finalizeLowering(MachineFunction &MF) const override; |
| 842 | |
| 843 | bool shouldLocalize(const MachineInstr &MI, |
| 844 | const TargetTransformInfo *TTI) const override; |
| 845 | |
| 846 | bool SimplifyDemandedBitsForTargetNode(SDValue Op, |
| 847 | const APInt &OriginalDemandedBits, |
| 848 | const APInt &OriginalDemandedElts, |
| 849 | KnownBits &Known, |
| 850 | TargetLoweringOpt &TLO, |
| 851 | unsigned Depth) const override; |
| 852 | |
| 853 | bool isTargetCanonicalConstantNode(SDValue Op) const override; |
| 854 | |
| 855 | // With the exception of data-predicate transitions, no instructions are |
| 856 | // required to cast between legal scalable vector types. However: |
| 857 | // 1. Packed and unpacked types have different bit lengths, meaning BITCAST |
| 858 | // is not universally useable. |
| 859 | // 2. Most unpacked integer types are not legal and thus integer extends |
| 860 | // cannot be used to convert between unpacked and packed types. |
| 861 | // These can make "bitcasting" a multiphase process. REINTERPRET_CAST is used |
| 862 | // to transition between unpacked and packed types of the same element type, |
| 863 | // with BITCAST used otherwise. |
| 864 | // This function does not handle predicate bitcasts. |
| 865 | SDValue getSVESafeBitCast(EVT VT, SDValue Op, SelectionDAG &DAG) const; |
| 866 | |
| 867 | // Returns the runtime value for PSTATE.SM by generating a call to |
| 868 | // __arm_sme_state. |
| 869 | SDValue getRuntimePStateSM(SelectionDAG &DAG, SDValue Chain, SDLoc DL, |
| 870 | EVT VT) const; |
| 871 | |
| 872 | bool preferScalarizeSplat(SDNode *N) const override; |
| 873 | |
| 874 | unsigned getMinimumJumpTableEntries() const override; |
| 875 | |
| 876 | bool softPromoteHalfType() const override { return true; } |
| 877 | |
| 878 | bool shouldScalarizeBinop(SDValue VecOp) const override { |
| 879 | return VecOp.getOpcode() == ISD::SETCC; |
| 880 | } |
| 881 | }; |
| 882 | |
| 883 | namespace AArch64 { |
| 884 | FastISel *createFastISel(FunctionLoweringInfo &funcInfo, |
| 885 | const TargetLibraryInfo *libInfo); |
| 886 | } // end namespace AArch64 |
| 887 | |
| 888 | } // end namespace llvm |
| 889 | |
| 890 | #endif |
| 891 | |