| 1 | //===- ARMISelLowering.h - ARM 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 ARM uses to lower LLVM code into a |
| 10 | // selection DAG. |
| 11 | // |
| 12 | //===----------------------------------------------------------------------===// |
| 13 | |
| 14 | #ifndef LLVM_LIB_TARGET_ARM_ARMISELLOWERING_H |
| 15 | #define LLVM_LIB_TARGET_ARM_ARMISELLOWERING_H |
| 16 | |
| 17 | #include "MCTargetDesc/ARMBaseInfo.h" |
| 18 | #include "llvm/ADT/SmallVector.h" |
| 19 | #include "llvm/ADT/StringRef.h" |
| 20 | #include "llvm/CodeGen/CallingConvLower.h" |
| 21 | #include "llvm/CodeGen/ISDOpcodes.h" |
| 22 | #include "llvm/CodeGen/MachineFunction.h" |
| 23 | #include "llvm/CodeGen/SelectionDAGNodes.h" |
| 24 | #include "llvm/CodeGen/TargetLowering.h" |
| 25 | #include "llvm/CodeGen/ValueTypes.h" |
| 26 | #include "llvm/CodeGenTypes/MachineValueType.h" |
| 27 | #include "llvm/IR/Attributes.h" |
| 28 | #include "llvm/IR/CallingConv.h" |
| 29 | #include "llvm/IR/Function.h" |
| 30 | #include "llvm/IR/InlineAsm.h" |
| 31 | #include "llvm/Support/CodeGen.h" |
| 32 | #include <optional> |
| 33 | #include <utility> |
| 34 | |
| 35 | namespace llvm { |
| 36 | |
| 37 | class ARMBaseTargetMachine; |
| 38 | class ARMSubtarget; |
| 39 | class DataLayout; |
| 40 | class FastISel; |
| 41 | class FunctionLoweringInfo; |
| 42 | class GlobalValue; |
| 43 | class InstrItineraryData; |
| 44 | class Instruction; |
| 45 | class IRBuilderBase; |
| 46 | class MachineBasicBlock; |
| 47 | class MachineInstr; |
| 48 | class SelectionDAG; |
| 49 | class TargetLibraryInfo; |
| 50 | class TargetMachine; |
| 51 | class TargetRegisterInfo; |
| 52 | class VectorType; |
| 53 | |
| 54 | namespace ARM { |
| 55 | /// Possible values of current rounding mode, which is specified in bits |
| 56 | /// 23:22 of FPSCR. |
| 57 | enum Rounding { |
| 58 | RN = 0, // Round to Nearest |
| 59 | RP = 1, // Round towards Plus infinity |
| 60 | RM = 2, // Round towards Minus infinity |
| 61 | RZ = 3, // Round towards Zero |
| 62 | rmMask = 3 // Bit mask selecting rounding mode |
| 63 | }; |
| 64 | |
| 65 | // Bit position of rounding mode bits in FPSCR. |
| 66 | const unsigned RoundingBitsPos = 22; |
| 67 | |
| 68 | // Bits of floating-point status. These are NZCV flags, QC bit and cumulative |
| 69 | // FP exception bits. |
| 70 | const unsigned FPStatusBits = 0xf800009f; |
| 71 | |
| 72 | // Some bits in the FPSCR are not yet defined. They must be preserved when |
| 73 | // modifying the contents. |
| 74 | const unsigned FPReservedBits = 0x00006060; |
| 75 | } // namespace ARM |
| 76 | |
| 77 | /// Define some predicates that are used for node matching. |
| 78 | namespace ARM { |
| 79 | |
| 80 | bool isBitFieldInvertedMask(unsigned v); |
| 81 | |
| 82 | } // end namespace ARM |
| 83 | |
| 84 | //===--------------------------------------------------------------------===// |
| 85 | // ARMTargetLowering - ARM Implementation of the TargetLowering interface |
| 86 | |
| 87 | class ARMTargetLowering : public TargetLowering { |
| 88 | // Copying needed for an outgoing byval argument. |
| 89 | enum ByValCopyKind { |
| 90 | // Argument is already in the correct location, no copy needed. |
| 91 | NoCopy, |
| 92 | // Argument value is currently in the local stack frame, needs copying to |
| 93 | // outgoing arguemnt area. |
| 94 | CopyOnce, |
| 95 | // Argument value is currently in the outgoing argument area, but not at |
| 96 | // the correct offset, so needs copying via a temporary in local stack |
| 97 | // space. |
| 98 | CopyViaTemp, |
| 99 | }; |
| 100 | |
| 101 | public: |
| 102 | explicit ARMTargetLowering(const TargetMachine &TM, |
| 103 | const ARMSubtarget &STI); |
| 104 | |
| 105 | const ARMBaseTargetMachine &getTM() const; |
| 106 | |
| 107 | unsigned getJumpTableEncoding() const override; |
| 108 | bool useSoftFloat() const override; |
| 109 | |
| 110 | SDValue LowerOperation(SDValue Op, SelectionDAG &DAG) const override; |
| 111 | |
| 112 | /// ReplaceNodeResults - Replace the results of node with an illegal result |
| 113 | /// type with new values built out of custom code. |
| 114 | void ReplaceNodeResults(SDNode *N, SmallVectorImpl<SDValue>&Results, |
| 115 | SelectionDAG &DAG) const override; |
| 116 | |
| 117 | bool isSelectSupported(SelectSupportKind Kind) const override { |
| 118 | // ARM does not support scalar condition selects on vectors. |
| 119 | return (Kind != ScalarCondVectorVal); |
| 120 | } |
| 121 | |
| 122 | bool isReadOnly(const GlobalValue *GV) const; |
| 123 | |
| 124 | /// getSetCCResultType - Return the value type to use for ISD::SETCC. |
| 125 | EVT getSetCCResultType(const DataLayout &DL, LLVMContext &Context, |
| 126 | EVT VT) const override; |
| 127 | |
| 128 | MachineBasicBlock * |
| 129 | EmitInstrWithCustomInserter(MachineInstr &MI, |
| 130 | MachineBasicBlock *MBB) const override; |
| 131 | |
| 132 | void AdjustInstrPostInstrSelection(MachineInstr &MI, |
| 133 | SDNode *Node) const override; |
| 134 | |
| 135 | bool supportKCFIBundles() const override; |
| 136 | |
| 137 | MachineInstr *EmitKCFICheck(MachineBasicBlock &MBB, |
| 138 | MachineBasicBlock::instr_iterator &MBBI, |
| 139 | const TargetInstrInfo *TII) const override; |
| 140 | |
| 141 | SDValue PerformCMOVCombine(SDNode *N, SelectionDAG &DAG) const; |
| 142 | SDValue PerformBRCONDCombine(SDNode *N, SelectionDAG &DAG) const; |
| 143 | SDValue PerformCMOVToBFICombine(SDNode *N, SelectionDAG &DAG) const; |
| 144 | SDValue PerformIntrinsicCombine(SDNode *N, DAGCombinerInfo &DCI) const; |
| 145 | SDValue PerformMVEExtCombine(SDNode *N, DAGCombinerInfo &DCI) const; |
| 146 | SDValue PerformMVETruncCombine(SDNode *N, DAGCombinerInfo &DCI) const; |
| 147 | SDValue PerformDAGCombine(SDNode *N, DAGCombinerInfo &DCI) const override; |
| 148 | |
| 149 | bool SimplifyDemandedBitsForTargetNode(SDValue Op, |
| 150 | const APInt &OriginalDemandedBits, |
| 151 | const APInt &OriginalDemandedElts, |
| 152 | KnownBits &Known, |
| 153 | TargetLoweringOpt &TLO, |
| 154 | unsigned Depth) const override; |
| 155 | |
| 156 | bool isDesirableToTransformToIntegerOp(unsigned Opc, EVT VT) const override; |
| 157 | |
| 158 | /// allowsMisalignedMemoryAccesses - Returns true if the target allows |
| 159 | /// unaligned memory accesses of the specified type. Returns whether it |
| 160 | /// is "fast" by reference in the second argument. |
| 161 | bool allowsMisalignedMemoryAccesses(EVT VT, unsigned AddrSpace, |
| 162 | Align Alignment, |
| 163 | MachineMemOperand::Flags Flags, |
| 164 | unsigned *Fast) const override; |
| 165 | |
| 166 | EVT getOptimalMemOpType(LLVMContext &Context, const MemOp &Op, |
| 167 | const AttributeList &FuncAttributes) const override; |
| 168 | |
| 169 | bool isTruncateFree(Type *SrcTy, Type *DstTy) const override; |
| 170 | bool isTruncateFree(EVT SrcVT, EVT DstVT) const override; |
| 171 | bool isZExtFree(SDValue Val, EVT VT2) const override; |
| 172 | Type* shouldConvertSplatType(ShuffleVectorInst* SVI) const override; |
| 173 | |
| 174 | bool isFNegFree(EVT VT) const override; |
| 175 | |
| 176 | bool isVectorLoadExtDesirable(SDValue ExtVal) const override; |
| 177 | |
| 178 | bool allowTruncateForTailCall(Type *Ty1, Type *Ty2) const override; |
| 179 | |
| 180 | |
| 181 | /// isLegalAddressingMode - Return true if the addressing mode represented |
| 182 | /// by AM is legal for this target, for a load/store of the specified type. |
| 183 | bool isLegalAddressingMode(const DataLayout &DL, const AddrMode &AM, |
| 184 | Type *Ty, unsigned AS, |
| 185 | Instruction *I = nullptr) const override; |
| 186 | |
| 187 | bool isLegalT2ScaledAddressingMode(const AddrMode &AM, EVT VT) const; |
| 188 | |
| 189 | /// Returns true if the addressing mode representing by AM is legal |
| 190 | /// for the Thumb1 target, for a load/store of the specified type. |
| 191 | bool isLegalT1ScaledAddressingMode(const AddrMode &AM, EVT VT) const; |
| 192 | |
| 193 | /// isLegalICmpImmediate - Return true if the specified immediate is legal |
| 194 | /// icmp immediate, that is the target has icmp instructions which can |
| 195 | /// compare a register against the immediate without having to materialize |
| 196 | /// the immediate into a register. |
| 197 | bool isLegalICmpImmediate(int64_t Imm) const override; |
| 198 | |
| 199 | /// isLegalAddImmediate - Return true if the specified immediate is legal |
| 200 | /// add immediate, that is the target has add instructions which can |
| 201 | /// add a register and the immediate without having to materialize |
| 202 | /// the immediate into a register. |
| 203 | bool isLegalAddImmediate(int64_t Imm) const override; |
| 204 | |
| 205 | /// getPreIndexedAddressParts - returns true by value, base pointer and |
| 206 | /// offset pointer and addressing mode by reference if the node's address |
| 207 | /// can be legally represented as pre-indexed load / store address. |
| 208 | bool getPreIndexedAddressParts(SDNode *N, SDValue &Base, SDValue &Offset, |
| 209 | ISD::MemIndexedMode &AM, |
| 210 | SelectionDAG &DAG) const override; |
| 211 | |
| 212 | /// getPostIndexedAddressParts - returns true by value, base pointer and |
| 213 | /// offset pointer and addressing mode by reference if this node can be |
| 214 | /// combined with a load / store to form a post-indexed load / store. |
| 215 | bool getPostIndexedAddressParts(SDNode *N, SDNode *Op, SDValue &Base, |
| 216 | SDValue &Offset, ISD::MemIndexedMode &AM, |
| 217 | SelectionDAG &DAG) const override; |
| 218 | |
| 219 | void computeKnownBitsForTargetNode(const SDValue Op, KnownBits &Known, |
| 220 | const APInt &DemandedElts, |
| 221 | const SelectionDAG &DAG, |
| 222 | unsigned Depth) const override; |
| 223 | |
| 224 | bool targetShrinkDemandedConstant(SDValue Op, const APInt &DemandedBits, |
| 225 | const APInt &DemandedElts, |
| 226 | TargetLoweringOpt &TLO) const override; |
| 227 | |
| 228 | ConstraintType getConstraintType(StringRef Constraint) const override; |
| 229 | |
| 230 | /// Examine constraint string and operand type and determine a weight value. |
| 231 | /// The operand object must already have been set up with the operand type. |
| 232 | ConstraintWeight getSingleConstraintMatchWeight( |
| 233 | AsmOperandInfo &info, const char *constraint) const override; |
| 234 | |
| 235 | std::pair<unsigned, const TargetRegisterClass *> |
| 236 | getRegForInlineAsmConstraint(const TargetRegisterInfo *TRI, |
| 237 | StringRef Constraint, MVT VT) const override; |
| 238 | |
| 239 | const char *LowerXConstraint(EVT ConstraintVT) const override; |
| 240 | |
| 241 | /// LowerAsmOperandForConstraint - Lower the specified operand into the Ops |
| 242 | /// vector. If it is invalid, don't add anything to Ops. If hasMemory is |
| 243 | /// true it means one of the asm constraint of the inline asm instruction |
| 244 | /// being processed is 'm'. |
| 245 | void LowerAsmOperandForConstraint(SDValue Op, StringRef Constraint, |
| 246 | std::vector<SDValue> &Ops, |
| 247 | SelectionDAG &DAG) const override; |
| 248 | |
| 249 | InlineAsm::ConstraintCode |
| 250 | getInlineAsmMemConstraint(StringRef ConstraintCode) const override { |
| 251 | if (ConstraintCode == "Q" ) |
| 252 | return InlineAsm::ConstraintCode::Q; |
| 253 | if (ConstraintCode.size() == 2) { |
| 254 | if (ConstraintCode[0] == 'U') { |
| 255 | switch(ConstraintCode[1]) { |
| 256 | default: |
| 257 | break; |
| 258 | case 'm': |
| 259 | return InlineAsm::ConstraintCode::Um; |
| 260 | case 'n': |
| 261 | return InlineAsm::ConstraintCode::Un; |
| 262 | case 'q': |
| 263 | return InlineAsm::ConstraintCode::Uq; |
| 264 | case 's': |
| 265 | return InlineAsm::ConstraintCode::Us; |
| 266 | case 't': |
| 267 | return InlineAsm::ConstraintCode::Ut; |
| 268 | case 'v': |
| 269 | return InlineAsm::ConstraintCode::Uv; |
| 270 | case 'y': |
| 271 | return InlineAsm::ConstraintCode::Uy; |
| 272 | } |
| 273 | } |
| 274 | } |
| 275 | return TargetLowering::getInlineAsmMemConstraint(ConstraintCode); |
| 276 | } |
| 277 | |
| 278 | const ARMSubtarget* getSubtarget() const { |
| 279 | return Subtarget; |
| 280 | } |
| 281 | |
| 282 | /// getRegClassFor - Return the register class that should be used for the |
| 283 | /// specified value type. |
| 284 | const TargetRegisterClass * |
| 285 | getRegClassFor(MVT VT, bool isDivergent = false) const override; |
| 286 | |
| 287 | bool shouldAlignPointerArgs(CallInst *CI, unsigned &MinSize, |
| 288 | Align &PrefAlign) const override; |
| 289 | |
| 290 | /// createFastISel - This method returns a target specific FastISel object, |
| 291 | /// or null if the target does not support "fast" ISel. |
| 292 | FastISel * |
| 293 | createFastISel(FunctionLoweringInfo &funcInfo, |
| 294 | const TargetLibraryInfo *libInfo, |
| 295 | const LibcallLoweringInfo *libcallLowering) const override; |
| 296 | |
| 297 | Sched::Preference getSchedulingPreference(SDNode *N) const override; |
| 298 | |
| 299 | bool preferZeroCompareBranch() const override { return true; } |
| 300 | |
| 301 | bool preferSelectsOverBooleanArithmetic(EVT VT) const override; |
| 302 | |
| 303 | bool isMaskAndCmp0FoldingBeneficial(const Instruction &AndI) const override; |
| 304 | |
| 305 | bool hasAndNotCompare(SDValue V) const override { |
| 306 | // We can use bics for any scalar. |
| 307 | return V.getValueType().isScalarInteger(); |
| 308 | } |
| 309 | |
| 310 | bool |
| 311 | isShuffleMaskLegal(ArrayRef<int> M, EVT VT) const override; |
| 312 | bool isOffsetFoldingLegal(const GlobalAddressSDNode *GA) const override; |
| 313 | |
| 314 | /// isFPImmLegal - Returns true if the target can instruction select the |
| 315 | /// specified FP immediate natively. If false, the legalizer will |
| 316 | /// materialize the FP immediate as a load from a constant pool. |
| 317 | bool isFPImmLegal(const APFloat &Imm, EVT VT, |
| 318 | bool ForCodeSize = false) const override; |
| 319 | |
| 320 | void getTgtMemIntrinsic(SmallVectorImpl<IntrinsicInfo> &Infos, |
| 321 | const CallBase &I, MachineFunction &MF, |
| 322 | unsigned Intrinsic) const override; |
| 323 | |
| 324 | /// Returns true if it is beneficial to convert a load of a constant |
| 325 | /// to just the constant itself. |
| 326 | bool shouldConvertConstantLoadToIntImm(const APInt &Imm, |
| 327 | Type *Ty) const override; |
| 328 | |
| 329 | /// Return true if EXTRACT_SUBVECTOR is cheap for this result type |
| 330 | /// with this index. |
| 331 | bool (EVT ResVT, EVT SrcVT, |
| 332 | unsigned Index) const override; |
| 333 | |
| 334 | bool shouldFormOverflowOp(unsigned Opcode, EVT VT, |
| 335 | bool MathUsed) const override { |
| 336 | // Using overflow ops for overflow checks only should beneficial on ARM. |
| 337 | return TargetLowering::shouldFormOverflowOp(Opcode, VT, MathUsed: true); |
| 338 | } |
| 339 | |
| 340 | bool shouldReassociateReduction(unsigned Opc, EVT VT) const override { |
| 341 | return Opc != ISD::VECREDUCE_ADD; |
| 342 | } |
| 343 | |
| 344 | /// Returns true if an argument of type Ty needs to be passed in a |
| 345 | /// contiguous block of registers in calling convention CallConv. |
| 346 | bool functionArgumentNeedsConsecutiveRegisters( |
| 347 | Type *Ty, CallingConv::ID CallConv, bool isVarArg, |
| 348 | const DataLayout &DL) const override; |
| 349 | |
| 350 | /// If a physical register, this returns the register that receives the |
| 351 | /// exception address on entry to an EH pad. |
| 352 | Register |
| 353 | getExceptionPointerRegister(const Constant *PersonalityFn) const override; |
| 354 | |
| 355 | /// If a physical register, this returns the register that receives the |
| 356 | /// exception typeid on entry to a landing pad. |
| 357 | Register |
| 358 | getExceptionSelectorRegister(const Constant *PersonalityFn) const override; |
| 359 | |
| 360 | Instruction *makeDMB(IRBuilderBase &Builder, ARM_MB::MemBOpt Domain) const; |
| 361 | Value *emitLoadLinked(IRBuilderBase &Builder, Type *ValueTy, Value *Addr, |
| 362 | AtomicOrdering Ord) const override; |
| 363 | Value *emitStoreConditional(IRBuilderBase &Builder, Value *Val, Value *Addr, |
| 364 | AtomicOrdering Ord) const override; |
| 365 | |
| 366 | void |
| 367 | emitAtomicCmpXchgNoStoreLLBalance(IRBuilderBase &Builder) const override; |
| 368 | |
| 369 | Instruction *emitLeadingFence(IRBuilderBase &Builder, Instruction *Inst, |
| 370 | AtomicOrdering Ord) const override; |
| 371 | Instruction *emitTrailingFence(IRBuilderBase &Builder, Instruction *Inst, |
| 372 | AtomicOrdering Ord) const override; |
| 373 | |
| 374 | unsigned getMaxSupportedInterleaveFactor() const override; |
| 375 | |
| 376 | bool lowerInterleavedLoad(Instruction *Load, Value *Mask, |
| 377 | ArrayRef<ShuffleVectorInst *> Shuffles, |
| 378 | ArrayRef<unsigned> Indices, unsigned Factor, |
| 379 | const APInt &GapMask) const override; |
| 380 | bool lowerInterleavedStore(Instruction *Store, Value *Mask, |
| 381 | ShuffleVectorInst *SVI, unsigned Factor, |
| 382 | const APInt &GapMask) const override; |
| 383 | |
| 384 | bool shouldInsertFencesForAtomic(const Instruction *I) const override; |
| 385 | TargetLoweringBase::AtomicExpansionKind |
| 386 | shouldExpandAtomicLoadInIR(LoadInst *LI) const override; |
| 387 | TargetLoweringBase::AtomicExpansionKind |
| 388 | shouldExpandAtomicStoreInIR(StoreInst *SI) const override; |
| 389 | TargetLoweringBase::AtomicExpansionKind |
| 390 | shouldExpandAtomicRMWInIR(const AtomicRMWInst *AI) const override; |
| 391 | TargetLoweringBase::AtomicExpansionKind |
| 392 | shouldExpandAtomicCmpXchgInIR(const AtomicCmpXchgInst *AI) const override; |
| 393 | |
| 394 | bool useLoadStackGuardNode(const Module &M) const override; |
| 395 | |
| 396 | void |
| 397 | insertSSPDeclarations(Module &M, |
| 398 | const LibcallLoweringInfo &Libcalls) const override; |
| 399 | |
| 400 | bool canCombineStoreAndExtract(Type *VectorTy, Value *Idx, |
| 401 | unsigned &Cost) const override; |
| 402 | |
| 403 | bool canCreateUndefOrPoisonForTargetNode( |
| 404 | SDValue Op, const APInt &DemandedElts, const SelectionDAG &DAG, |
| 405 | bool PoisonOnly, bool ConsiderFlags, unsigned Depth) const override; |
| 406 | |
| 407 | bool canMergeStoresTo(unsigned AddressSpace, EVT MemVT, |
| 408 | const MachineFunction &MF) const override { |
| 409 | // Do not merge to larger than i32. |
| 410 | return (MemVT.getSizeInBits() <= 32); |
| 411 | } |
| 412 | |
| 413 | bool isCheapToSpeculateCttz(Type *Ty) const override; |
| 414 | bool isCheapToSpeculateCtlz(Type *Ty) const override; |
| 415 | |
| 416 | bool convertSetCCLogicToBitwiseLogic(EVT VT) const override { |
| 417 | return VT.isScalarInteger(); |
| 418 | } |
| 419 | |
| 420 | bool supportSwiftError() const override { |
| 421 | return true; |
| 422 | } |
| 423 | |
| 424 | bool supportSplitCSR(MachineFunction *MF) const override { |
| 425 | return MF->getFunction().getCallingConv() == CallingConv::CXX_FAST_TLS && |
| 426 | MF->getFunction().hasFnAttribute(Kind: Attribute::NoUnwind); |
| 427 | } |
| 428 | |
| 429 | bool hasStandaloneRem(EVT VT) const override { |
| 430 | return HasStandaloneRem; |
| 431 | } |
| 432 | |
| 433 | ShiftLegalizationStrategy |
| 434 | preferredShiftLegalizationStrategy(SelectionDAG &DAG, SDNode *N, |
| 435 | unsigned ExpansionFactor) const override; |
| 436 | |
| 437 | CCAssignFn *CCAssignFnForCall(CallingConv::ID CC, bool isVarArg) const; |
| 438 | CCAssignFn *CCAssignFnForReturn(CallingConv::ID CC, bool isVarArg) const; |
| 439 | |
| 440 | /// Returns true if \p VecTy is a legal interleaved access type. This |
| 441 | /// function checks the vector element type and the overall width of the |
| 442 | /// vector. |
| 443 | bool isLegalInterleavedAccessType(unsigned Factor, FixedVectorType *VecTy, |
| 444 | Align Alignment, |
| 445 | const DataLayout &DL) const; |
| 446 | |
| 447 | bool isMulAddWithConstProfitable(SDValue AddNode, |
| 448 | SDValue ConstNode) const override; |
| 449 | |
| 450 | bool alignLoopsWithOptSize() const override; |
| 451 | |
| 452 | /// Returns the number of interleaved accesses that will be generated when |
| 453 | /// lowering accesses of the given type. |
| 454 | unsigned getNumInterleavedAccesses(VectorType *VecTy, |
| 455 | const DataLayout &DL) const; |
| 456 | |
| 457 | void finalizeLowering(MachineFunction &MF) const override; |
| 458 | |
| 459 | /// Return the correct alignment for the current calling convention. |
| 460 | Align getABIAlignmentForCallingConv(Type *ArgTy, |
| 461 | const DataLayout &DL) const override; |
| 462 | |
| 463 | bool isDesirableToCommuteWithShift(const SDNode *N, |
| 464 | CombineLevel Level) const override; |
| 465 | |
| 466 | bool isDesirableToCommuteXorWithShift(const SDNode *N) const override; |
| 467 | |
| 468 | bool shouldFoldConstantShiftPairToMask(const SDNode *N) const override; |
| 469 | |
| 470 | /// Return true if it is profitable to fold a pair of shifts into a mask. |
| 471 | bool shouldFoldMaskToVariableShiftPair(SDValue Y) const override { |
| 472 | EVT VT = Y.getValueType(); |
| 473 | |
| 474 | if (VT.isVector()) |
| 475 | return false; |
| 476 | |
| 477 | return VT.getScalarSizeInBits() <= 32; |
| 478 | } |
| 479 | |
| 480 | bool shouldFoldSelectWithIdentityConstant(unsigned BinOpcode, EVT VT, |
| 481 | unsigned SelectOpcode, SDValue X, |
| 482 | SDValue Y) const override; |
| 483 | |
| 484 | bool preferIncOfAddToSubOfNot(EVT VT) const override; |
| 485 | |
| 486 | bool shouldConvertFpToSat(unsigned Op, EVT FPVT, EVT VT) const override; |
| 487 | |
| 488 | bool isComplexDeinterleavingSupported() const override; |
| 489 | bool isComplexDeinterleavingOperationSupported( |
| 490 | ComplexDeinterleavingOperation Operation, Type *Ty) const override; |
| 491 | |
| 492 | Value *createComplexDeinterleavingIR( |
| 493 | IRBuilderBase &B, ComplexDeinterleavingOperation OperationType, |
| 494 | ComplexDeinterleavingRotation Rotation, Value *InputA, Value *InputB, |
| 495 | Value *Accumulator = nullptr) const override; |
| 496 | |
| 497 | bool useFPRegsForHalfType() const override { return true; } |
| 498 | |
| 499 | protected: |
| 500 | std::pair<const TargetRegisterClass *, uint8_t> |
| 501 | findRepresentativeClass(const TargetRegisterInfo *TRI, |
| 502 | MVT VT) const override; |
| 503 | |
| 504 | private: |
| 505 | /// Subtarget - Keep a pointer to the ARMSubtarget around so that we can |
| 506 | /// make the right decision when generating code for different targets. |
| 507 | const ARMSubtarget *Subtarget; |
| 508 | |
| 509 | const TargetRegisterInfo *RegInfo; |
| 510 | |
| 511 | const InstrItineraryData *Itins; |
| 512 | |
| 513 | // TODO: remove this, and have shouldInsertFencesForAtomic do the proper |
| 514 | // check. |
| 515 | bool InsertFencesForAtomic; |
| 516 | |
| 517 | bool HasStandaloneRem = true; |
| 518 | |
| 519 | void addTypeForNEON(MVT VT, MVT PromotedLdStVT); |
| 520 | void addDRTypeForNEON(MVT VT); |
| 521 | void addQRTypeForNEON(MVT VT); |
| 522 | std::pair<SDValue, SDValue> getARMXALUOOp(SDValue Op, SelectionDAG &DAG, SDValue &ARMcc) const; |
| 523 | |
| 524 | using RegsToPassVector = SmallVector<std::pair<unsigned, SDValue>, 8>; |
| 525 | |
| 526 | void PassF64ArgInRegs(const SDLoc &dl, SelectionDAG &DAG, SDValue Chain, |
| 527 | SDValue &Arg, RegsToPassVector &RegsToPass, |
| 528 | CCValAssign &VA, CCValAssign &NextVA, |
| 529 | SDValue &StackPtr, |
| 530 | SmallVectorImpl<SDValue> &MemOpChains, |
| 531 | bool IsTailCall, |
| 532 | int SPDiff) const; |
| 533 | SDValue GetF64FormalArgument(CCValAssign &VA, CCValAssign &NextVA, |
| 534 | SDValue &Root, SelectionDAG &DAG, |
| 535 | const SDLoc &dl) const; |
| 536 | |
| 537 | CallingConv::ID getEffectiveCallingConv(CallingConv::ID CC, |
| 538 | bool isVarArg) const; |
| 539 | CCAssignFn *CCAssignFnForNode(CallingConv::ID CC, bool Return, |
| 540 | bool isVarArg) const; |
| 541 | std::pair<SDValue, MachinePointerInfo> |
| 542 | computeAddrForCallArg(const SDLoc &dl, SelectionDAG &DAG, |
| 543 | const CCValAssign &VA, SDValue StackPtr, |
| 544 | bool IsTailCall, int SPDiff) const; |
| 545 | ByValCopyKind ByValNeedsCopyForTailCall(SelectionDAG &DAG, SDValue Src, |
| 546 | SDValue Dst, |
| 547 | ISD::ArgFlagsTy Flags) const; |
| 548 | SDValue LowerEH_SJLJ_SETJMP(SDValue Op, SelectionDAG &DAG) const; |
| 549 | SDValue LowerEH_SJLJ_LONGJMP(SDValue Op, SelectionDAG &DAG) const; |
| 550 | SDValue LowerEH_SJLJ_SETUP_DISPATCH(SDValue Op, SelectionDAG &DAG) const; |
| 551 | SDValue LowerINTRINSIC_VOID(SDValue Op, SelectionDAG &DAG, |
| 552 | const ARMSubtarget *Subtarget) const; |
| 553 | SDValue LowerINTRINSIC_WO_CHAIN(SDValue Op, SelectionDAG &DAG, |
| 554 | const ARMSubtarget *Subtarget) const; |
| 555 | SDValue LowerBlockAddress(SDValue Op, SelectionDAG &DAG) const; |
| 556 | SDValue LowerConstantPool(SDValue Op, SelectionDAG &DAG) const; |
| 557 | SDValue LowerGlobalAddress(SDValue Op, SelectionDAG &DAG) const; |
| 558 | SDValue LowerGlobalAddressDarwin(SDValue Op, SelectionDAG &DAG) const; |
| 559 | SDValue LowerGlobalAddressELF(SDValue Op, SelectionDAG &DAG) const; |
| 560 | SDValue LowerGlobalAddressWindows(SDValue Op, SelectionDAG &DAG) const; |
| 561 | SDValue LowerGlobalTLSAddress(SDValue Op, SelectionDAG &DAG) const; |
| 562 | SDValue LowerToTLSGeneralDynamicModel(GlobalAddressSDNode *GA, |
| 563 | SelectionDAG &DAG) const; |
| 564 | SDValue LowerToTLSExecModels(GlobalAddressSDNode *GA, |
| 565 | SelectionDAG &DAG, |
| 566 | TLSModel::Model model) const; |
| 567 | SDValue LowerGlobalTLSAddressDarwin(SDValue Op, SelectionDAG &DAG) const; |
| 568 | SDValue LowerGlobalTLSAddressWindows(SDValue Op, SelectionDAG &DAG) const; |
| 569 | SDValue LowerBR_JT(SDValue Op, SelectionDAG &DAG) const; |
| 570 | SDValue LowerSignedALUO(SDValue Op, SelectionDAG &DAG) const; |
| 571 | SDValue LowerUnsignedALUO(SDValue Op, SelectionDAG &DAG) const; |
| 572 | SDValue LowerSELECT(SDValue Op, SelectionDAG &DAG) const; |
| 573 | SDValue LowerSELECT_CC(SDValue Op, SelectionDAG &DAG) const; |
| 574 | SDValue LowerBRCOND(SDValue Op, SelectionDAG &DAG) const; |
| 575 | SDValue LowerBR_CC(SDValue Op, SelectionDAG &DAG) const; |
| 576 | SDValue LowerFCOPYSIGN(SDValue Op, SelectionDAG &DAG) const; |
| 577 | SDValue LowerRETURNADDR(SDValue Op, SelectionDAG &DAG) const; |
| 578 | SDValue LowerFRAMEADDR(SDValue Op, SelectionDAG &DAG) const; |
| 579 | SDValue LowerShiftRightParts(SDValue Op, SelectionDAG &DAG) const; |
| 580 | SDValue LowerShiftLeftParts(SDValue Op, SelectionDAG &DAG) const; |
| 581 | SDValue LowerGET_ROUNDING(SDValue Op, SelectionDAG &DAG) const; |
| 582 | SDValue LowerSET_ROUNDING(SDValue Op, SelectionDAG &DAG) const; |
| 583 | SDValue LowerSET_FPMODE(SDValue Op, SelectionDAG &DAG) const; |
| 584 | SDValue LowerRESET_FPMODE(SDValue Op, SelectionDAG &DAG) const; |
| 585 | SDValue LowerConstantFP(SDValue Op, SelectionDAG &DAG, |
| 586 | const ARMSubtarget *ST) const; |
| 587 | SDValue LowerBUILD_VECTOR(SDValue Op, SelectionDAG &DAG, |
| 588 | const ARMSubtarget *ST) const; |
| 589 | SDValue LowerINSERT_VECTOR_ELT(SDValue Op, SelectionDAG &DAG) const; |
| 590 | SDValue LowerDivRem(SDValue Op, SelectionDAG &DAG) const; |
| 591 | SDValue LowerDIV_Windows(SDValue Op, SelectionDAG &DAG, bool Signed) const; |
| 592 | void ExpandDIV_Windows(SDValue Op, SelectionDAG &DAG, bool Signed, |
| 593 | SmallVectorImpl<SDValue> &Results) const; |
| 594 | SDValue ExpandBITCAST(SDNode *N, SelectionDAG &DAG, |
| 595 | const ARMSubtarget *Subtarget) const; |
| 596 | SDValue LowerWindowsDIVLibCall(SDValue Op, SelectionDAG &DAG, bool Signed, |
| 597 | SDValue &Chain) const; |
| 598 | SDValue LowerREM(SDNode *N, SelectionDAG &DAG) const; |
| 599 | SDValue LowerDYNAMIC_STACKALLOC(SDValue Op, SelectionDAG &DAG) const; |
| 600 | SDValue LowerFP_ROUND(SDValue Op, SelectionDAG &DAG) const; |
| 601 | SDValue LowerFP_EXTEND(SDValue Op, SelectionDAG &DAG) const; |
| 602 | SDValue LowerFP_TO_INT(SDValue Op, SelectionDAG &DAG) const; |
| 603 | SDValue LowerINT_TO_FP(SDValue Op, SelectionDAG &DAG) const; |
| 604 | SDValue LowerFSETCC(SDValue Op, SelectionDAG &DAG) const; |
| 605 | SDValue LowerSPONENTRY(SDValue Op, SelectionDAG &DAG) const; |
| 606 | void LowerLOAD(SDNode *N, SmallVectorImpl<SDValue> &Results, |
| 607 | SelectionDAG &DAG) const; |
| 608 | SDValue LowerSTORE(SDValue Op, SelectionDAG &DAG, |
| 609 | const ARMSubtarget *Subtarget) const; |
| 610 | std::pair<SDValue, SDValue> |
| 611 | LowerAEABIUnalignedLoad(SDValue Op, SelectionDAG &DAG) const; |
| 612 | SDValue LowerAEABIUnalignedStore(SDValue Op, SelectionDAG &DAG) const; |
| 613 | SDValue LowerFP_TO_BF16(SDValue Op, SelectionDAG &DAG) const; |
| 614 | SDValue LowerCMP(SDValue Op, SelectionDAG &DAG) const; |
| 615 | SDValue LowerABS(SDValue Op, SelectionDAG &DAG) const; |
| 616 | Register getRegisterByName(const char* RegName, LLT VT, |
| 617 | const MachineFunction &MF) const override; |
| 618 | |
| 619 | SDValue BuildSDIVPow2(SDNode *N, const APInt &Divisor, SelectionDAG &DAG, |
| 620 | SmallVectorImpl<SDNode *> &Created) const override; |
| 621 | |
| 622 | bool isFMAFasterThanFMulAndFAdd(const MachineFunction &MF, |
| 623 | EVT VT) const override; |
| 624 | |
| 625 | SDValue MoveToHPR(const SDLoc &dl, SelectionDAG &DAG, MVT LocVT, MVT ValVT, |
| 626 | SDValue Val) const; |
| 627 | SDValue MoveFromHPR(const SDLoc &dl, SelectionDAG &DAG, MVT LocVT, |
| 628 | MVT ValVT, SDValue Val) const; |
| 629 | |
| 630 | SDValue ReconstructShuffle(SDValue Op, SelectionDAG &DAG) const; |
| 631 | |
| 632 | SDValue LowerCallResult(SDValue Chain, SDValue InGlue, |
| 633 | CallingConv::ID CallConv, bool isVarArg, |
| 634 | const SmallVectorImpl<ISD::InputArg> &Ins, |
| 635 | const SDLoc &dl, SelectionDAG &DAG, |
| 636 | SmallVectorImpl<SDValue> &InVals, bool isThisReturn, |
| 637 | SDValue ThisVal, bool isCmseNSCall) const; |
| 638 | |
| 639 | void initializeSplitCSR(MachineBasicBlock *Entry) const override; |
| 640 | void insertCopiesSplitCSR( |
| 641 | MachineBasicBlock *Entry, |
| 642 | const SmallVectorImpl<MachineBasicBlock *> &Exits) const override; |
| 643 | |
| 644 | bool splitValueIntoRegisterParts( |
| 645 | SelectionDAG & DAG, const SDLoc &DL, SDValue Val, SDValue *Parts, |
| 646 | unsigned NumParts, MVT PartVT, std::optional<CallingConv::ID> CC) |
| 647 | const override; |
| 648 | |
| 649 | SDValue joinRegisterPartsIntoValue( |
| 650 | SelectionDAG & DAG, const SDLoc &DL, const SDValue *Parts, |
| 651 | unsigned NumParts, MVT PartVT, EVT ValueVT, |
| 652 | std::optional<CallingConv::ID> CC) const override; |
| 653 | |
| 654 | SDValue |
| 655 | LowerFormalArguments(SDValue Chain, CallingConv::ID CallConv, bool isVarArg, |
| 656 | const SmallVectorImpl<ISD::InputArg> &Ins, |
| 657 | const SDLoc &dl, SelectionDAG &DAG, |
| 658 | SmallVectorImpl<SDValue> &InVals) const override; |
| 659 | |
| 660 | int StoreByValRegs(CCState &CCInfo, SelectionDAG &DAG, const SDLoc &dl, |
| 661 | SDValue &Chain, const Value *OrigArg, |
| 662 | unsigned InRegsParamRecordIdx, int ArgOffset, |
| 663 | unsigned ArgSize) const; |
| 664 | |
| 665 | void VarArgStyleRegisters(CCState &CCInfo, SelectionDAG &DAG, |
| 666 | const SDLoc &dl, SDValue &Chain, |
| 667 | unsigned ArgOffset, unsigned TotalArgRegsSaveSize, |
| 668 | bool ForceMutable = false) const; |
| 669 | |
| 670 | SDValue LowerCall(TargetLowering::CallLoweringInfo &CLI, |
| 671 | SmallVectorImpl<SDValue> &InVals) const override; |
| 672 | |
| 673 | /// HandleByVal - Target-specific cleanup for ByVal support. |
| 674 | void HandleByVal(CCState *, unsigned &, Align) const override; |
| 675 | |
| 676 | /// IsEligibleForTailCallOptimization - Check whether the call is eligible |
| 677 | /// for tail call optimization. Targets which want to do tail call |
| 678 | /// optimization should implement this function. |
| 679 | bool IsEligibleForTailCallOptimization( |
| 680 | TargetLowering::CallLoweringInfo &CLI, CCState &CCInfo, |
| 681 | SmallVectorImpl<CCValAssign> &ArgLocs, const bool isIndirect) const; |
| 682 | |
| 683 | bool CanLowerReturn(CallingConv::ID CallConv, |
| 684 | MachineFunction &MF, bool isVarArg, |
| 685 | const SmallVectorImpl<ISD::OutputArg> &Outs, |
| 686 | LLVMContext &Context, const Type *RetTy) const override; |
| 687 | |
| 688 | SDValue LowerReturn(SDValue Chain, CallingConv::ID CallConv, bool isVarArg, |
| 689 | const SmallVectorImpl<ISD::OutputArg> &Outs, |
| 690 | const SmallVectorImpl<SDValue> &OutVals, |
| 691 | const SDLoc &dl, SelectionDAG &DAG) const override; |
| 692 | |
| 693 | bool isUsedByReturnOnly(SDNode *N, SDValue &Chain) const override; |
| 694 | |
| 695 | bool mayBeEmittedAsTailCall(const CallInst *CI) const override; |
| 696 | |
| 697 | bool shouldConsiderGEPOffsetSplit() const override { return true; } |
| 698 | |
| 699 | bool isUnsupportedFloatingType(EVT VT) const; |
| 700 | |
| 701 | ArrayRef<MCPhysReg> getRoundingControlRegisters() const override; |
| 702 | |
| 703 | SDValue getCMOV(const SDLoc &dl, EVT VT, SDValue FalseVal, SDValue TrueVal, |
| 704 | SDValue ARMcc, SDValue Flags, SelectionDAG &DAG) const; |
| 705 | SDValue getARMCmp(SDValue LHS, SDValue RHS, ISD::CondCode CC, |
| 706 | SDValue &ARMcc, SelectionDAG &DAG, const SDLoc &dl) const; |
| 707 | SDValue getVFPCmp(SDValue LHS, SDValue RHS, SelectionDAG &DAG, |
| 708 | const SDLoc &dl, bool Signaling = false) const; |
| 709 | |
| 710 | SDValue OptimizeVFPBrcond(SDValue Op, SelectionDAG &DAG) const; |
| 711 | |
| 712 | void SetupEntryBlockForSjLj(MachineInstr &MI, MachineBasicBlock *MBB, |
| 713 | MachineBasicBlock *DispatchBB, int FI) const; |
| 714 | |
| 715 | void EmitSjLjDispatchBlock(MachineInstr &MI, MachineBasicBlock *MBB) const; |
| 716 | |
| 717 | MachineBasicBlock *EmitStructByval(MachineInstr &MI, |
| 718 | MachineBasicBlock *MBB) const; |
| 719 | |
| 720 | MachineBasicBlock *EmitLowered__chkstk(MachineInstr &MI, |
| 721 | MachineBasicBlock *MBB) const; |
| 722 | MachineBasicBlock *EmitLowered__dbzchk(MachineInstr &MI, |
| 723 | MachineBasicBlock *MBB) const; |
| 724 | void addMVEVectorTypes(bool HasMVEFP); |
| 725 | void addAllExtLoads(const MVT From, const MVT To, LegalizeAction Action); |
| 726 | void setAllExpand(MVT VT); |
| 727 | }; |
| 728 | |
| 729 | enum VMOVModImmType { |
| 730 | VMOVModImm, |
| 731 | VMVNModImm, |
| 732 | MVEVMVNModImm, |
| 733 | OtherModImm |
| 734 | }; |
| 735 | |
| 736 | namespace ARM { |
| 737 | |
| 738 | FastISel *createFastISel(FunctionLoweringInfo &funcInfo, |
| 739 | const TargetLibraryInfo *libInfo, |
| 740 | const LibcallLoweringInfo *libcallLowering); |
| 741 | |
| 742 | } // end namespace ARM |
| 743 | |
| 744 | } // end namespace llvm |
| 745 | |
| 746 | #endif // LLVM_LIB_TARGET_ARM_ARMISELLOWERING_H |
| 747 | |