brintos

brintos / llvm-project-archived public Read only

0
0
Text · 40.9 KiB · 04e2ab0 Raw
995 lines · c
1//===-- ARMBaseInstrInfo.h - ARM Base Instruction Information ---*- 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-exception6//7//===----------------------------------------------------------------------===//8//9// This file contains the Base ARM implementation of the TargetInstrInfo class.10//11//===----------------------------------------------------------------------===//12 13#ifndef LLVM_LIB_TARGET_ARM_ARMBASEINSTRINFO_H14#define LLVM_LIB_TARGET_ARM_ARMBASEINSTRINFO_H15 16#include "ARMBaseRegisterInfo.h"17#include "MCTargetDesc/ARMBaseInfo.h"18#include "MCTargetDesc/ARMMCTargetDesc.h"19#include "llvm/ADT/DenseMap.h"20#include "llvm/ADT/SmallSet.h"21#include "llvm/CodeGen/MachineBasicBlock.h"22#include "llvm/CodeGen/MachineInstr.h"23#include "llvm/CodeGen/MachineInstrBuilder.h"24#include "llvm/CodeGen/MachineOperand.h"25#include "llvm/CodeGen/MachineRegisterInfo.h"26#include "llvm/CodeGen/Register.h"27#include "llvm/CodeGen/TargetInstrInfo.h"28#include "llvm/IR/IntrinsicInst.h"29#include "llvm/IR/IntrinsicsARM.h"30#include "llvm/Support/ErrorHandling.h"31#include <array>32#include <cstdint>33 34#define GET_INSTRINFO_HEADER35#include "ARMGenInstrInfo.inc"36 37namespace llvm {38 39class ARMBaseRegisterInfo;40class ARMSubtarget;41 42class ARMBaseInstrInfo : public ARMGenInstrInfo {43  const ARMSubtarget &Subtarget;44 45protected:46  // Can be only subclassed.47  explicit ARMBaseInstrInfo(const ARMSubtarget &STI,48                            const ARMBaseRegisterInfo &TRI);49 50  void expandLoadStackGuardBase(MachineBasicBlock::iterator MI,51                                unsigned LoadImmOpc, unsigned LoadOpc) const;52 53  /// Build the equivalent inputs of a REG_SEQUENCE for the given \p MI54  /// and \p DefIdx.55  /// \p [out] InputRegs of the equivalent REG_SEQUENCE. Each element of56  /// the list is modeled as <Reg:SubReg, SubIdx>.57  /// E.g., REG_SEQUENCE %1:sub1, sub0, %2, sub1 would produce58  /// two elements:59  /// - %1:sub1, sub060  /// - %2<:0>, sub161  ///62  /// \returns true if it is possible to build such an input sequence63  /// with the pair \p MI, \p DefIdx. False otherwise.64  ///65  /// \pre MI.isRegSequenceLike().66  bool getRegSequenceLikeInputs(67      const MachineInstr &MI, unsigned DefIdx,68      SmallVectorImpl<RegSubRegPairAndIdx> &InputRegs) const override;69 70  /// Build the equivalent inputs of a EXTRACT_SUBREG for the given \p MI71  /// and \p DefIdx.72  /// \p [out] InputReg of the equivalent EXTRACT_SUBREG.73  /// E.g., EXTRACT_SUBREG %1:sub1, sub0, sub1 would produce:74  /// - %1:sub1, sub075  ///76  /// \returns true if it is possible to build such an input sequence77  /// with the pair \p MI, \p DefIdx. False otherwise.78  ///79  /// \pre MI.isExtractSubregLike().80  bool getExtractSubregLikeInputs(const MachineInstr &MI, unsigned DefIdx,81                                  RegSubRegPairAndIdx &InputReg) const override;82 83  /// Build the equivalent inputs of a INSERT_SUBREG for the given \p MI84  /// and \p DefIdx.85  /// \p [out] BaseReg and \p [out] InsertedReg contain86  /// the equivalent inputs of INSERT_SUBREG.87  /// E.g., INSERT_SUBREG %0:sub0, %1:sub1, sub3 would produce:88  /// - BaseReg: %0:sub089  /// - InsertedReg: %1:sub1, sub390  ///91  /// \returns true if it is possible to build such an input sequence92  /// with the pair \p MI, \p DefIdx. False otherwise.93  ///94  /// \pre MI.isInsertSubregLike().95  bool96  getInsertSubregLikeInputs(const MachineInstr &MI, unsigned DefIdx,97                            RegSubRegPair &BaseReg,98                            RegSubRegPairAndIdx &InsertedReg) const override;99 100  /// Commutes the operands in the given instruction.101  /// The commutable operands are specified by their indices OpIdx1 and OpIdx2.102  ///103  /// Do not call this method for a non-commutable instruction or for104  /// non-commutable pair of operand indices OpIdx1 and OpIdx2.105  /// Even though the instruction is commutable, the method may still106  /// fail to commute the operands, null pointer is returned in such cases.107  MachineInstr *commuteInstructionImpl(MachineInstr &MI, bool NewMI,108                                       unsigned OpIdx1,109                                       unsigned OpIdx2) const override;110  /// If the specific machine instruction is an instruction that moves/copies111  /// value from one register to another register return destination and source112  /// registers as machine operands.113  std::optional<DestSourcePair>114  isCopyInstrImpl(const MachineInstr &MI) const override;115 116  /// Specialization of \ref TargetInstrInfo::describeLoadedValue, used to117  /// enhance debug entry value descriptions for ARM targets.118  std::optional<ParamLoadedValue>119  describeLoadedValue(const MachineInstr &MI, Register Reg) const override;120 121public:122  // Return whether the target has an explicit NOP encoding.123  bool hasNOP() const;124 125  // Return the non-pre/post incrementing version of 'Opc'. Return 0126  // if there is not such an opcode.127  virtual unsigned getUnindexedOpcode(unsigned Opc) const = 0;128 129  const ARMBaseRegisterInfo &getRegisterInfo() const {130    return static_cast<const ARMBaseRegisterInfo &>(131        TargetInstrInfo::getRegisterInfo());132  }133 134  const ARMSubtarget &getSubtarget() const { return Subtarget; }135 136  ScheduleHazardRecognizer *137  CreateTargetHazardRecognizer(const TargetSubtargetInfo *STI,138                               const ScheduleDAG *DAG) const override;139 140  ScheduleHazardRecognizer *141  CreateTargetMIHazardRecognizer(const InstrItineraryData *II,142                                 const ScheduleDAGMI *DAG) const override;143 144  ScheduleHazardRecognizer *145  CreateTargetPostRAHazardRecognizer(const InstrItineraryData *II,146                                     const ScheduleDAG *DAG) const override;147 148  // Branch analysis.149  bool analyzeBranch(MachineBasicBlock &MBB, MachineBasicBlock *&TBB,150                     MachineBasicBlock *&FBB,151                     SmallVectorImpl<MachineOperand> &Cond,152                     bool AllowModify = false) const override;153  unsigned removeBranch(MachineBasicBlock &MBB,154                        int *BytesRemoved = nullptr) const override;155  unsigned insertBranch(MachineBasicBlock &MBB, MachineBasicBlock *TBB,156                        MachineBasicBlock *FBB, ArrayRef<MachineOperand> Cond,157                        const DebugLoc &DL,158                        int *BytesAdded = nullptr) const override;159 160  bool161  reverseBranchCondition(SmallVectorImpl<MachineOperand> &Cond) const override;162 163  // Predication support.164  bool isPredicated(const MachineInstr &MI) const override;165 166  // MIR printer helper function to annotate Operands with a comment.167  std::string168  createMIROperandComment(const MachineInstr &MI, const MachineOperand &Op,169                          unsigned OpIdx,170                          const TargetRegisterInfo *TRI) const override;171 172  ARMCC::CondCodes getPredicate(const MachineInstr &MI) const {173    int PIdx = MI.findFirstPredOperandIdx();174    return PIdx != -1 ? (ARMCC::CondCodes)MI.getOperand(PIdx).getImm()175                      : ARMCC::AL;176  }177 178  bool PredicateInstruction(MachineInstr &MI,179                            ArrayRef<MachineOperand> Pred) const override;180 181  bool SubsumesPredicate(ArrayRef<MachineOperand> Pred1,182                         ArrayRef<MachineOperand> Pred2) const override;183 184  bool ClobbersPredicate(MachineInstr &MI, std::vector<MachineOperand> &Pred,185                         bool SkipDead) const override;186 187  bool isPredicable(const MachineInstr &MI) const override;188 189  // CPSR defined in instruction190  static bool isCPSRDefined(const MachineInstr &MI);191 192  /// GetInstSize - Returns the size of the specified MachineInstr.193  ///194  unsigned getInstSizeInBytes(const MachineInstr &MI) const override;195 196  Register isLoadFromStackSlot(const MachineInstr &MI,197                               int &FrameIndex) const override;198  Register isStoreToStackSlot(const MachineInstr &MI,199                              int &FrameIndex) const override;200  Register isLoadFromStackSlotPostFE(const MachineInstr &MI,201                                     int &FrameIndex) const override;202  Register isStoreToStackSlotPostFE(const MachineInstr &MI,203                                    int &FrameIndex) const override;204 205  void copyToCPSR(MachineBasicBlock &MBB, MachineBasicBlock::iterator I,206                  MCRegister SrcReg, bool KillSrc,207                  const ARMSubtarget &Subtarget) const;208  void copyFromCPSR(MachineBasicBlock &MBB, MachineBasicBlock::iterator I,209                    MCRegister DestReg, bool KillSrc,210                    const ARMSubtarget &Subtarget) const;211 212  void copyPhysReg(MachineBasicBlock &MBB, MachineBasicBlock::iterator I,213                   const DebugLoc &DL, Register DestReg, Register SrcReg,214                   bool KillSrc, bool RenamableDest = false,215                   bool RenamableSrc = false) const override;216 217  void storeRegToStackSlot(218      MachineBasicBlock &MBB, MachineBasicBlock::iterator MBBI, Register SrcReg,219      bool isKill, int FrameIndex, const TargetRegisterClass *RC, Register VReg,220      MachineInstr::MIFlag Flags = MachineInstr::NoFlags) const override;221 222  void loadRegFromStackSlot(223      MachineBasicBlock &MBB, MachineBasicBlock::iterator MBBI,224      Register DestReg, int FrameIndex, const TargetRegisterClass *RC,225      Register VReg,226      MachineInstr::MIFlag Flags = MachineInstr::NoFlags) const override;227 228  bool expandPostRAPseudo(MachineInstr &MI) const override;229 230  bool shouldSink(const MachineInstr &MI) const override;231 232  void reMaterialize(MachineBasicBlock &MBB, MachineBasicBlock::iterator MI,233                     Register DestReg, unsigned SubIdx,234                     const MachineInstr &Orig) const override;235 236  MachineInstr &237  duplicate(MachineBasicBlock &MBB, MachineBasicBlock::iterator InsertBefore,238            const MachineInstr &Orig) const override;239 240  const MachineInstrBuilder &AddDReg(MachineInstrBuilder &MIB, unsigned Reg,241                                     unsigned SubIdx, unsigned State) const;242 243  bool produceSameValue(const MachineInstr &MI0, const MachineInstr &MI1,244                        const MachineRegisterInfo *MRI) const override;245 246  /// areLoadsFromSameBasePtr - This is used by the pre-regalloc scheduler to247  /// determine if two loads are loading from the same base address. It should248  /// only return true if the base pointers are the same and the only249  /// differences between the two addresses is the offset. It also returns the250  /// offsets by reference.251  bool areLoadsFromSameBasePtr(SDNode *Load1, SDNode *Load2, int64_t &Offset1,252                               int64_t &Offset2) const override;253 254  /// shouldScheduleLoadsNear - This is a used by the pre-regalloc scheduler to255  /// determine (in conjunction with areLoadsFromSameBasePtr) if two loads256  /// should be scheduled togther. On some targets if two loads are loading from257  /// addresses in the same cache line, it's better if they are scheduled258  /// together. This function takes two integers that represent the load offsets259  /// from the common base address. It returns true if it decides it's desirable260  /// to schedule the two loads together. "NumLoads" is the number of loads that261  /// have already been scheduled after Load1.262  bool shouldScheduleLoadsNear(SDNode *Load1, SDNode *Load2,263                               int64_t Offset1, int64_t Offset2,264                               unsigned NumLoads) const override;265 266  bool isSchedulingBoundary(const MachineInstr &MI,267                            const MachineBasicBlock *MBB,268                            const MachineFunction &MF) const override;269 270  bool isProfitableToIfCvt(MachineBasicBlock &MBB,271                           unsigned NumCycles, unsigned ExtraPredCycles,272                           BranchProbability Probability) const override;273 274  bool isProfitableToIfCvt(MachineBasicBlock &TMBB, unsigned NumT,275                           unsigned ExtraT, MachineBasicBlock &FMBB,276                           unsigned NumF, unsigned ExtraF,277                           BranchProbability Probability) const override;278 279  bool isProfitableToDupForIfCvt(MachineBasicBlock &MBB, unsigned NumCycles,280                                 BranchProbability Probability) const override {281    return NumCycles == 1;282  }283 284  unsigned extraSizeToPredicateInstructions(const MachineFunction &MF,285                                            unsigned NumInsts) const override;286  unsigned predictBranchSizeForIfCvt(MachineInstr &MI) const override;287 288  bool isProfitableToUnpredicate(MachineBasicBlock &TMBB,289                                 MachineBasicBlock &FMBB) const override;290 291  /// analyzeCompare - For a comparison instruction, return the source registers292  /// in SrcReg and SrcReg2 if having two register operands, and the value it293  /// compares against in CmpValue. Return true if the comparison instruction294  /// can be analyzed.295  bool analyzeCompare(const MachineInstr &MI, Register &SrcReg,296                      Register &SrcReg2, int64_t &CmpMask,297                      int64_t &CmpValue) const override;298 299  /// optimizeCompareInstr - Convert the instruction to set the zero flag so300  /// that we can remove a "comparison with zero"; Remove a redundant CMP301  /// instruction if the flags can be updated in the same way by an earlier302  /// instruction such as SUB.303  bool optimizeCompareInstr(MachineInstr &CmpInstr, Register SrcReg,304                            Register SrcReg2, int64_t CmpMask, int64_t CmpValue,305                            const MachineRegisterInfo *MRI) const override;306 307  bool analyzeSelect(const MachineInstr &MI,308                     SmallVectorImpl<MachineOperand> &Cond, unsigned &TrueOp,309                     unsigned &FalseOp, bool &Optimizable) const override;310 311  MachineInstr *optimizeSelect(MachineInstr &MI,312                               SmallPtrSetImpl<MachineInstr *> &SeenMIs,313                               bool) const override;314 315  /// foldImmediate - 'Reg' is known to be defined by a move immediate316  /// instruction, try to fold the immediate into the use instruction.317  bool foldImmediate(MachineInstr &UseMI, MachineInstr &DefMI, Register Reg,318                     MachineRegisterInfo *MRI) const override;319 320  unsigned getNumMicroOps(const InstrItineraryData *ItinData,321                          const MachineInstr &MI) const override;322 323  std::optional<unsigned> getOperandLatency(const InstrItineraryData *ItinData,324                                            const MachineInstr &DefMI,325                                            unsigned DefIdx,326                                            const MachineInstr &UseMI,327                                            unsigned UseIdx) const override;328  std::optional<unsigned> getOperandLatency(const InstrItineraryData *ItinData,329                                            SDNode *DefNode, unsigned DefIdx,330                                            SDNode *UseNode,331                                            unsigned UseIdx) const override;332 333  /// VFP/NEON execution domains.334  std::pair<uint16_t, uint16_t>335  getExecutionDomain(const MachineInstr &MI) const override;336  void setExecutionDomain(MachineInstr &MI, unsigned Domain) const override;337 338  unsigned339  getPartialRegUpdateClearance(const MachineInstr &, unsigned,340                               const TargetRegisterInfo *) const override;341  void breakPartialRegDependency(MachineInstr &, unsigned,342                                 const TargetRegisterInfo *TRI) const override;343 344  /// Get the number of addresses by LDM or VLDM or zero for unknown.345  unsigned getNumLDMAddresses(const MachineInstr &MI) const;346 347  std::pair<unsigned, unsigned>348  decomposeMachineOperandsTargetFlags(unsigned TF) const override;349  ArrayRef<std::pair<unsigned, const char *>>350  getSerializableDirectMachineOperandTargetFlags() const override;351  ArrayRef<std::pair<unsigned, const char *>>352  getSerializableBitmaskMachineOperandTargetFlags() const override;353 354  /// ARM supports the MachineOutliner.355  bool isFunctionSafeToOutlineFrom(MachineFunction &MF,356                                   bool OutlineFromLinkOnceODRs) const override;357  std::optional<std::unique_ptr<outliner::OutlinedFunction>>358  getOutliningCandidateInfo(359      const MachineModuleInfo &MMI,360      std::vector<outliner::Candidate> &RepeatedSequenceLocs,361      unsigned MinRepeats) const override;362  void mergeOutliningCandidateAttributes(363      Function &F, std::vector<outliner::Candidate> &Candidates) const override;364  outliner::InstrType getOutliningTypeImpl(const MachineModuleInfo &MMI,365                                           MachineBasicBlock::iterator &MIT,366                                           unsigned Flags) const override;367  bool isMBBSafeToOutlineFrom(MachineBasicBlock &MBB,368                              unsigned &Flags) const override;369  void buildOutlinedFrame(MachineBasicBlock &MBB, MachineFunction &MF,370                          const outliner::OutlinedFunction &OF) const override;371  MachineBasicBlock::iterator372  insertOutlinedCall(Module &M, MachineBasicBlock &MBB,373                     MachineBasicBlock::iterator &It, MachineFunction &MF,374                     outliner::Candidate &C) const override;375 376  /// Enable outlining by default at -Oz.377  bool shouldOutlineFromFunctionByDefault(MachineFunction &MF) const override;378 379  bool isUnspillableTerminatorImpl(const MachineInstr *MI) const override {380    return MI->getOpcode() == ARM::t2LoopEndDec ||381           MI->getOpcode() == ARM::t2DoLoopStartTP ||382           MI->getOpcode() == ARM::t2WhileLoopStartLR ||383           MI->getOpcode() == ARM::t2WhileLoopStartTP;384  }385 386  /// Analyze loop L, which must be a single-basic-block loop, and if the387  /// conditions can be understood enough produce a PipelinerLoopInfo object.388  std::unique_ptr<TargetInstrInfo::PipelinerLoopInfo>389  analyzeLoopForPipelining(MachineBasicBlock *LoopBB) const override;390 391private:392  /// Returns an unused general-purpose register which can be used for393  /// constructing an outlined call if one exists. Returns 0 otherwise.394  Register findRegisterToSaveLRTo(outliner::Candidate &C) const;395 396  /// Adds an instruction which saves the link register on top of the stack into397  /// the MachineBasicBlock \p MBB at position \p It. If \p Auth is true,398  /// compute and store an authentication code alongiside the link register.399  /// If \p CFI is true, emit CFI instructions.400  void saveLROnStack(MachineBasicBlock &MBB, MachineBasicBlock::iterator It,401                     bool CFI, bool Auth) const;402 403  /// Adds an instruction which restores the link register from the top the404  /// stack into the MachineBasicBlock \p MBB at position \p It. If \p Auth is405  /// true, restore an authentication code and authenticate LR.406  /// If \p CFI is true, emit CFI instructions.407  void restoreLRFromStack(MachineBasicBlock &MBB,408                          MachineBasicBlock::iterator It, bool CFI,409                          bool Auth) const;410 411  /// \brief Sets the offsets on outlined instructions in \p MBB which use SP412  /// so that they will be valid post-outlining.413  ///414  /// \param MBB A \p MachineBasicBlock in an outlined function.415  void fixupPostOutline(MachineBasicBlock &MBB) const;416 417  /// Returns true if the machine instruction offset can handle the stack fixup418  /// and updates it if requested.419  bool checkAndUpdateStackOffset(MachineInstr *MI, int64_t Fixup,420                                 bool Updt) const;421 422  unsigned getInstBundleLength(const MachineInstr &MI) const;423 424  std::optional<unsigned> getVLDMDefCycle(const InstrItineraryData *ItinData,425                                          const MCInstrDesc &DefMCID,426                                          unsigned DefClass, unsigned DefIdx,427                                          unsigned DefAlign) const;428  std::optional<unsigned> getLDMDefCycle(const InstrItineraryData *ItinData,429                                         const MCInstrDesc &DefMCID,430                                         unsigned DefClass, unsigned DefIdx,431                                         unsigned DefAlign) const;432  std::optional<unsigned> getVSTMUseCycle(const InstrItineraryData *ItinData,433                                          const MCInstrDesc &UseMCID,434                                          unsigned UseClass, unsigned UseIdx,435                                          unsigned UseAlign) const;436  std::optional<unsigned> getSTMUseCycle(const InstrItineraryData *ItinData,437                                         const MCInstrDesc &UseMCID,438                                         unsigned UseClass, unsigned UseIdx,439                                         unsigned UseAlign) const;440  std::optional<unsigned> getOperandLatency(const InstrItineraryData *ItinData,441                                            const MCInstrDesc &DefMCID,442                                            unsigned DefIdx, unsigned DefAlign,443                                            const MCInstrDesc &UseMCID,444                                            unsigned UseIdx,445                                            unsigned UseAlign) const;446 447  std::optional<unsigned> getOperandLatencyImpl(448      const InstrItineraryData *ItinData, const MachineInstr &DefMI,449      unsigned DefIdx, const MCInstrDesc &DefMCID, unsigned DefAdj,450      const MachineOperand &DefMO, unsigned Reg, const MachineInstr &UseMI,451      unsigned UseIdx, const MCInstrDesc &UseMCID, unsigned UseAdj) const;452 453  unsigned getPredicationCost(const MachineInstr &MI) const override;454 455  unsigned getInstrLatency(const InstrItineraryData *ItinData,456                           const MachineInstr &MI,457                           unsigned *PredCost = nullptr) const override;458 459  unsigned getInstrLatency(const InstrItineraryData *ItinData,460                           SDNode *Node) const override;461 462  bool hasHighOperandLatency(const TargetSchedModel &SchedModel,463                             const MachineRegisterInfo *MRI,464                             const MachineInstr &DefMI, unsigned DefIdx,465                             const MachineInstr &UseMI,466                             unsigned UseIdx) const override;467  bool hasLowDefLatency(const TargetSchedModel &SchedModel,468                        const MachineInstr &DefMI,469                        unsigned DefIdx) const override;470 471  /// verifyInstruction - Perform target specific instruction verification.472  bool verifyInstruction(const MachineInstr &MI,473                         StringRef &ErrInfo) const override;474 475  virtual void expandLoadStackGuard(MachineBasicBlock::iterator MI) const = 0;476 477  void expandMEMCPY(MachineBasicBlock::iterator) const;478 479  /// Identify instructions that can be folded into a MOVCC instruction, and480  /// return the defining instruction.481  MachineInstr *canFoldIntoMOVCC(Register Reg, const MachineRegisterInfo &MRI,482                                 const TargetInstrInfo *TII) const;483 484  bool isReMaterializableImpl(const MachineInstr &MI) const override;485 486private:487  /// Modeling special VFP / NEON fp MLA / MLS hazards.488 489  /// MLxEntryMap - Map fp MLA / MLS to the corresponding entry in the internal490  /// MLx table.491  DenseMap<unsigned, unsigned> MLxEntryMap;492 493  /// MLxHazardOpcodes - Set of add / sub and multiply opcodes that would cause494  /// stalls when scheduled together with fp MLA / MLS opcodes.495  SmallSet<unsigned, 16> MLxHazardOpcodes;496 497public:498  /// isFpMLxInstruction - Return true if the specified opcode is a fp MLA / MLS499  /// instruction.500  bool isFpMLxInstruction(unsigned Opcode) const {501    return MLxEntryMap.count(Opcode);502  }503 504  /// isFpMLxInstruction - This version also returns the multiply opcode and the505  /// addition / subtraction opcode to expand to. Return true for 'HasLane' for506  /// the MLX instructions with an extra lane operand.507  bool isFpMLxInstruction(unsigned Opcode, unsigned &MulOpc,508                          unsigned &AddSubOpc, bool &NegAcc,509                          bool &HasLane) const;510 511  /// canCauseFpMLxStall - Return true if an instruction of the specified opcode512  /// will cause stalls when scheduled after (within 4-cycle window) a fp513  /// MLA / MLS instruction.514  bool canCauseFpMLxStall(unsigned Opcode) const {515    return MLxHazardOpcodes.count(Opcode);516  }517 518  /// Returns true if the instruction has a shift by immediate that can be519  /// executed in one cycle less.520  bool isSwiftFastImmShift(const MachineInstr *MI) const;521 522  /// Returns predicate register associated with the given frame instruction.523  unsigned getFramePred(const MachineInstr &MI) const {524    assert(isFrameInstr(MI));525    // Operands of ADJCALLSTACKDOWN/ADJCALLSTACKUP:526    // - argument declared in the pattern:527    // 0 - frame size528    // 1 - arg of CALLSEQ_START/CALLSEQ_END529    // 2 - predicate code (like ARMCC::AL)530    // - added by predOps:531    // 3 - predicate reg532    return MI.getOperand(3).getReg();533  }534 535  std::optional<RegImmPair> isAddImmediate(const MachineInstr &MI,536                                           Register Reg) const override;537};538 539/// Get the operands corresponding to the given \p Pred value. By default, the540/// predicate register is assumed to be 0 (no register), but you can pass in a541/// \p PredReg if that is not the case.542static inline std::array<MachineOperand, 2> predOps(ARMCC::CondCodes Pred,543                                                    unsigned PredReg = 0) {544  return {{MachineOperand::CreateImm(static_cast<int64_t>(Pred)),545           MachineOperand::CreateReg(PredReg, false)}};546}547 548/// Get the operand corresponding to the conditional code result. By default,549/// this is 0 (no register).550static inline MachineOperand condCodeOp(unsigned CCReg = 0) {551  return MachineOperand::CreateReg(CCReg, false);552}553 554/// Get the operand corresponding to the conditional code result for Thumb1.555/// This operand will always refer to CPSR and it will have the Define flag set.556/// You can optionally set the Dead flag by means of \p isDead.557static inline MachineOperand t1CondCodeOp(bool isDead = false) {558  return MachineOperand::CreateReg(ARM::CPSR,559                                   /*Define*/ true, /*Implicit*/ false,560                                   /*Kill*/ false, isDead);561}562 563static inline564bool isUncondBranchOpcode(int Opc) {565  return Opc == ARM::B || Opc == ARM::tB || Opc == ARM::t2B;566}567 568// This table shows the VPT instruction variants, i.e. the different569// mask field encodings, see also B5.6. Predication/conditional execution in570// the ArmARM.571static inline bool isVPTOpcode(int Opc) {572  return Opc == ARM::MVE_VPTv16i8 || Opc == ARM::MVE_VPTv16u8 ||573         Opc == ARM::MVE_VPTv16s8 || Opc == ARM::MVE_VPTv8i16 ||574         Opc == ARM::MVE_VPTv8u16 || Opc == ARM::MVE_VPTv8s16 ||575         Opc == ARM::MVE_VPTv4i32 || Opc == ARM::MVE_VPTv4u32 ||576         Opc == ARM::MVE_VPTv4s32 || Opc == ARM::MVE_VPTv4f32 ||577         Opc == ARM::MVE_VPTv8f16 || Opc == ARM::MVE_VPTv16i8r ||578         Opc == ARM::MVE_VPTv16u8r || Opc == ARM::MVE_VPTv16s8r ||579         Opc == ARM::MVE_VPTv8i16r || Opc == ARM::MVE_VPTv8u16r ||580         Opc == ARM::MVE_VPTv8s16r || Opc == ARM::MVE_VPTv4i32r ||581         Opc == ARM::MVE_VPTv4u32r || Opc == ARM::MVE_VPTv4s32r ||582         Opc == ARM::MVE_VPTv4f32r || Opc == ARM::MVE_VPTv8f16r ||583         Opc == ARM::MVE_VPST;584}585 586static inline587unsigned VCMPOpcodeToVPT(unsigned Opcode) {588  switch (Opcode) {589  default:590    return 0;591  case ARM::MVE_VCMPf32:592    return ARM::MVE_VPTv4f32;593  case ARM::MVE_VCMPf16:594    return ARM::MVE_VPTv8f16;595  case ARM::MVE_VCMPi8:596    return ARM::MVE_VPTv16i8;597  case ARM::MVE_VCMPi16:598    return ARM::MVE_VPTv8i16;599  case ARM::MVE_VCMPi32:600    return ARM::MVE_VPTv4i32;601  case ARM::MVE_VCMPu8:602    return ARM::MVE_VPTv16u8;603  case ARM::MVE_VCMPu16:604    return ARM::MVE_VPTv8u16;605  case ARM::MVE_VCMPu32:606    return ARM::MVE_VPTv4u32;607  case ARM::MVE_VCMPs8:608    return ARM::MVE_VPTv16s8;609  case ARM::MVE_VCMPs16:610    return ARM::MVE_VPTv8s16;611  case ARM::MVE_VCMPs32:612    return ARM::MVE_VPTv4s32;613 614  case ARM::MVE_VCMPf32r:615    return ARM::MVE_VPTv4f32r;616  case ARM::MVE_VCMPf16r:617    return ARM::MVE_VPTv8f16r;618  case ARM::MVE_VCMPi8r:619    return ARM::MVE_VPTv16i8r;620  case ARM::MVE_VCMPi16r:621    return ARM::MVE_VPTv8i16r;622  case ARM::MVE_VCMPi32r:623    return ARM::MVE_VPTv4i32r;624  case ARM::MVE_VCMPu8r:625    return ARM::MVE_VPTv16u8r;626  case ARM::MVE_VCMPu16r:627    return ARM::MVE_VPTv8u16r;628  case ARM::MVE_VCMPu32r:629    return ARM::MVE_VPTv4u32r;630  case ARM::MVE_VCMPs8r:631    return ARM::MVE_VPTv16s8r;632  case ARM::MVE_VCMPs16r:633    return ARM::MVE_VPTv8s16r;634  case ARM::MVE_VCMPs32r:635    return ARM::MVE_VPTv4s32r;636  }637}638 639static inline640bool isCondBranchOpcode(int Opc) {641  return Opc == ARM::Bcc || Opc == ARM::tBcc || Opc == ARM::t2Bcc;642}643 644static inline bool isJumpTableBranchOpcode(int Opc) {645  return Opc == ARM::BR_JTr || Opc == ARM::BR_JTm_i12 ||646         Opc == ARM::BR_JTm_rs || Opc == ARM::BR_JTadd || Opc == ARM::tBR_JTr ||647         Opc == ARM::t2BR_JT;648}649 650static inline651bool isIndirectBranchOpcode(int Opc) {652  return Opc == ARM::BX || Opc == ARM::MOVPCRX || Opc == ARM::tBRIND;653}654 655static inline bool isIndirectCall(const MachineInstr &MI) {656  int Opc = MI.getOpcode();657  switch (Opc) {658    // indirect calls:659  case ARM::BLX:660  case ARM::BLX_noip:661  case ARM::BLX_pred:662  case ARM::BLX_pred_noip:663  case ARM::BX_CALL:664  case ARM::BMOVPCRX_CALL:665  case ARM::TCRETURNri:666  case ARM::TCRETURNrinotr12:667  case ARM::TAILJMPr:668  case ARM::TAILJMPr4:669  case ARM::tBLXr:670  case ARM::tBLXr_noip:671  case ARM::tBLXNSr:672  case ARM::tBLXNS_CALL:673  case ARM::tBX_CALL:674  case ARM::tTAILJMPr:675    assert(MI.isCall(MachineInstr::IgnoreBundle));676    return true;677    // direct calls:678  case ARM::BL:679  case ARM::BL_pred:680  case ARM::BMOVPCB_CALL:681  case ARM::BL_PUSHLR:682  case ARM::BLXi:683  case ARM::TCRETURNdi:684  case ARM::TAILJMPd:685  case ARM::SVC:686  case ARM::HVC:687  case ARM::TPsoft:688  case ARM::tTAILJMPd:689  case ARM::t2SMC:690  case ARM::t2HVC:691  case ARM::tBL:692  case ARM::tBLXi:693  case ARM::tBL_PUSHLR:694  case ARM::tTAILJMPdND:695  case ARM::tSVC:696  case ARM::tTPsoft:697    assert(MI.isCall(MachineInstr::IgnoreBundle));698    return false;699  }700  assert(!MI.isCall(MachineInstr::IgnoreBundle));701  return false;702}703 704static inline bool isIndirectControlFlowNotComingBack(const MachineInstr &MI) {705  int opc = MI.getOpcode();706  return MI.isReturn() || isIndirectBranchOpcode(MI.getOpcode()) ||707         isJumpTableBranchOpcode(opc);708}709 710static inline bool isSpeculationBarrierEndBBOpcode(int Opc) {711  return Opc == ARM::SpeculationBarrierISBDSBEndBB ||712         Opc == ARM::SpeculationBarrierSBEndBB ||713         Opc == ARM::t2SpeculationBarrierISBDSBEndBB ||714         Opc == ARM::t2SpeculationBarrierSBEndBB;715}716 717static inline bool isPopOpcode(int Opc) {718  return Opc == ARM::tPOP_RET || Opc == ARM::LDMIA_RET ||719         Opc == ARM::t2LDMIA_RET || Opc == ARM::tPOP || Opc == ARM::LDMIA_UPD ||720         Opc == ARM::t2LDMIA_UPD || Opc == ARM::VLDMDIA_UPD;721}722 723static inline bool isPushOpcode(int Opc) {724  return Opc == ARM::tPUSH || Opc == ARM::t2STMDB_UPD ||725         Opc == ARM::STMDB_UPD || Opc == ARM::VSTMDDB_UPD;726}727 728static inline bool isSubImmOpcode(int Opc) {729  return Opc == ARM::SUBri ||730         Opc == ARM::tSUBi3 || Opc == ARM::tSUBi8 ||731         Opc == ARM::tSUBSi3 || Opc == ARM::tSUBSi8 ||732         Opc == ARM::t2SUBri || Opc == ARM::t2SUBri12 || Opc == ARM::t2SUBSri;733}734 735static inline bool isMovRegOpcode(int Opc) {736  return Opc == ARM::MOVr || Opc == ARM::tMOVr || Opc == ARM::t2MOVr;737}738/// isValidCoprocessorNumber - decide whether an explicit coprocessor739/// number is legal in generic instructions like CDP. The answer can740/// vary with the subtarget.741static inline bool isValidCoprocessorNumber(unsigned Num,742                                            const FeatureBitset& featureBits) {743  // In Armv7 and Armv8-M CP10 and CP11 clash with VFP/NEON, however, the744  // coprocessor is still valid for CDP/MCR/MRC and friends. Allowing it is745  // useful for code which is shared with older architectures which do not know746  // the new VFP/NEON mnemonics.747 748  // Armv8-A disallows everything *other* than 111x (CP14 and CP15).749  if (featureBits[ARM::HasV8Ops] && (Num & 0xE) != 0xE)750    return false;751 752  // Armv8.1-M disallows 100x (CP8,CP9) and 111x (CP14,CP15)753  // which clash with MVE.754  if (featureBits[ARM::HasV8_1MMainlineOps] &&755      ((Num & 0xE) == 0x8 || (Num & 0xE) == 0xE))756    return false;757 758  return true;759}760 761static inline bool isSEHInstruction(const MachineInstr &MI) {762  unsigned Opc = MI.getOpcode();763  switch (Opc) {764  case ARM::SEH_StackAlloc:765  case ARM::SEH_SaveRegs:766  case ARM::SEH_SaveRegs_Ret:767  case ARM::SEH_SaveSP:768  case ARM::SEH_SaveFRegs:769  case ARM::SEH_SaveLR:770  case ARM::SEH_Nop:771  case ARM::SEH_Nop_Ret:772  case ARM::SEH_PrologEnd:773  case ARM::SEH_EpilogStart:774  case ARM::SEH_EpilogEnd:775    return true;776  default:777    return false;778  }779}780 781/// getInstrPredicate - If instruction is predicated, returns its predicate782/// condition, otherwise returns AL. It also returns the condition code783/// register by reference.784ARMCC::CondCodes getInstrPredicate(const MachineInstr &MI, Register &PredReg);785 786unsigned getMatchingCondBranchOpcode(unsigned Opc);787 788/// Map pseudo instructions that imply an 'S' bit onto real opcodes. Whether789/// the instruction is encoded with an 'S' bit is determined by the optional790/// CPSR def operand.791unsigned convertAddSubFlagsOpcode(unsigned OldOpc);792 793/// emitARMRegPlusImmediate / emitT2RegPlusImmediate - Emits a series of794/// instructions to materializea destreg = basereg + immediate in ARM / Thumb2795/// code.796void emitARMRegPlusImmediate(MachineBasicBlock &MBB,797                             MachineBasicBlock::iterator &MBBI,798                             const DebugLoc &dl, Register DestReg,799                             Register BaseReg, int NumBytes,800                             ARMCC::CondCodes Pred, Register PredReg,801                             const ARMBaseInstrInfo &TII, unsigned MIFlags = 0);802 803void emitT2RegPlusImmediate(MachineBasicBlock &MBB,804                            MachineBasicBlock::iterator &MBBI,805                            const DebugLoc &dl, Register DestReg,806                            Register BaseReg, int NumBytes,807                            ARMCC::CondCodes Pred, Register PredReg,808                            const ARMBaseInstrInfo &TII, unsigned MIFlags = 0);809void emitThumbRegPlusImmediate(MachineBasicBlock &MBB,810                               MachineBasicBlock::iterator &MBBI,811                               const DebugLoc &dl, Register DestReg,812                               Register BaseReg, int NumBytes,813                               const TargetInstrInfo &TII,814                               const ARMBaseRegisterInfo &MRI,815                               unsigned MIFlags = 0);816 817/// Tries to add registers to the reglist of a given base-updating818/// push/pop instruction to adjust the stack by an additional819/// NumBytes. This can save a few bytes per function in code-size, but820/// obviously generates more memory traffic. As such, it only takes821/// effect in functions being optimised for size.822bool tryFoldSPUpdateIntoPushPop(const ARMSubtarget &Subtarget,823                                MachineFunction &MF, MachineInstr *MI,824                                unsigned NumBytes);825 826/// rewriteARMFrameIndex / rewriteT2FrameIndex -827/// Rewrite MI to access 'Offset' bytes from the FP. Return false if the828/// offset could not be handled directly in MI, and return the left-over829/// portion by reference.830bool rewriteARMFrameIndex(MachineInstr &MI, unsigned FrameRegIdx,831                          Register FrameReg, int &Offset,832                          const ARMBaseInstrInfo &TII);833 834bool rewriteT2FrameIndex(MachineInstr &MI, unsigned FrameRegIdx,835                         Register FrameReg, int &Offset,836                         const ARMBaseInstrInfo &TII,837                         const TargetRegisterInfo *TRI);838 839/// Return true if Reg is defd between From and To840bool registerDefinedBetween(unsigned Reg, MachineBasicBlock::iterator From,841                            MachineBasicBlock::iterator To,842                            const TargetRegisterInfo *TRI);843 844/// Search backwards from a tBcc to find a tCMPi8 against 0, meaning845/// we can convert them to a tCBZ or tCBNZ. Return nullptr if not found.846MachineInstr *findCMPToFoldIntoCBZ(MachineInstr *Br,847                                   const TargetRegisterInfo *TRI);848 849void addUnpredicatedMveVpredNOp(MachineInstrBuilder &MIB);850void addUnpredicatedMveVpredROp(MachineInstrBuilder &MIB, Register DestReg);851 852void addPredicatedMveVpredNOp(MachineInstrBuilder &MIB, unsigned Cond);853void addPredicatedMveVpredROp(MachineInstrBuilder &MIB, unsigned Cond,854                              unsigned Inactive);855 856/// Returns the number of instructions required to materialize the given857/// constant in a register, or 3 if a literal pool load is needed.858/// If ForCodesize is specified, an approximate cost in bytes is returned.859unsigned ConstantMaterializationCost(unsigned Val,860                                     const ARMSubtarget *Subtarget,861                                     bool ForCodesize = false);862 863/// Returns true if Val1 has a lower Constant Materialization Cost than Val2.864/// Uses the cost from ConstantMaterializationCost, first with ForCodesize as865/// specified. If the scores are equal, return the comparison for !ForCodesize.866bool HasLowerConstantMaterializationCost(unsigned Val1, unsigned Val2,867                                         const ARMSubtarget *Subtarget,868                                         bool ForCodesize = false);869 870// Return the immediate if this is ADDri or SUBri, scaled as appropriate.871// Returns 0 for unknown instructions.872inline int getAddSubImmediate(MachineInstr &MI) {873  int Scale = 1;874  unsigned ImmOp;875  switch (MI.getOpcode()) {876  case ARM::t2ADDri:877    ImmOp = 2;878    break;879  case ARM::t2SUBri:880  case ARM::t2SUBri12:881    ImmOp = 2;882    Scale = -1;883    break;884  case ARM::tSUBi3:885  case ARM::tSUBi8:886    ImmOp = 3;887    Scale = -1;888    break;889  default:890    return 0;891  }892  return Scale * MI.getOperand(ImmOp).getImm();893}894 895// Given a memory access Opcode, check that the give Imm would be a valid Offset896// for this instruction using its addressing mode.897inline bool isLegalAddressImm(unsigned Opcode, int Imm,898                              const TargetInstrInfo *TII) {899  const MCInstrDesc &Desc = TII->get(Opcode);900  unsigned AddrMode = (Desc.TSFlags & ARMII::AddrModeMask);901  switch (AddrMode) {902  case ARMII::AddrModeT2_i7:903    return std::abs(Imm) < ((1 << 7) * 1);904  case ARMII::AddrModeT2_i7s2:905    return std::abs(Imm) < ((1 << 7) * 2) && Imm % 2 == 0;906  case ARMII::AddrModeT2_i7s4:907    return std::abs(Imm) < ((1 << 7) * 4) && Imm % 4 == 0;908  case ARMII::AddrModeT2_i8:909    return std::abs(Imm) < ((1 << 8) * 1);910  case ARMII::AddrModeT2_i8pos:911    return Imm >= 0 && Imm < ((1 << 8) * 1);912  case ARMII::AddrModeT2_i8neg:913    return Imm < 0 && -Imm < ((1 << 8) * 1);914  case ARMII::AddrModeT2_i8s4:915    return std::abs(Imm) < ((1 << 8) * 4) && Imm % 4 == 0;916  case ARMII::AddrModeT2_i12:917    return Imm >= 0 && Imm < ((1 << 12) * 1);918  case ARMII::AddrMode2:919    return std::abs(Imm) < ((1 << 12) * 1);920  default:921    llvm_unreachable("Unhandled Addressing mode");922  }923}924 925// Return true if the given intrinsic is a gather926inline bool isGather(IntrinsicInst *IntInst) {927  if (IntInst == nullptr)928    return false;929  unsigned IntrinsicID = IntInst->getIntrinsicID();930  return (IntrinsicID == Intrinsic::masked_gather ||931          IntrinsicID == Intrinsic::arm_mve_vldr_gather_base ||932          IntrinsicID == Intrinsic::arm_mve_vldr_gather_base_predicated ||933          IntrinsicID == Intrinsic::arm_mve_vldr_gather_base_wb ||934          IntrinsicID == Intrinsic::arm_mve_vldr_gather_base_wb_predicated ||935          IntrinsicID == Intrinsic::arm_mve_vldr_gather_offset ||936          IntrinsicID == Intrinsic::arm_mve_vldr_gather_offset_predicated);937}938 939// Return true if the given intrinsic is a scatter940inline bool isScatter(IntrinsicInst *IntInst) {941  if (IntInst == nullptr)942    return false;943  unsigned IntrinsicID = IntInst->getIntrinsicID();944  return (IntrinsicID == Intrinsic::masked_scatter ||945          IntrinsicID == Intrinsic::arm_mve_vstr_scatter_base ||946          IntrinsicID == Intrinsic::arm_mve_vstr_scatter_base_predicated ||947          IntrinsicID == Intrinsic::arm_mve_vstr_scatter_base_wb ||948          IntrinsicID == Intrinsic::arm_mve_vstr_scatter_base_wb_predicated ||949          IntrinsicID == Intrinsic::arm_mve_vstr_scatter_offset ||950          IntrinsicID == Intrinsic::arm_mve_vstr_scatter_offset_predicated);951}952 953// Return true if the given intrinsic is a gather or scatter954inline bool isGatherScatter(IntrinsicInst *IntInst) {955  if (IntInst == nullptr)956    return false;957  return isGather(IntInst) || isScatter(IntInst);958}959 960unsigned getBLXOpcode(const MachineFunction &MF);961unsigned gettBLXrOpcode(const MachineFunction &MF);962unsigned getBLXpredOpcode(const MachineFunction &MF);963 964inline bool isMVEVectorInstruction(const MachineInstr *MI) {965  // This attempts to remove non-mve instructions (scalar shifts), which966  // are just DPU CX instruction.967  switch (MI->getOpcode()) {968  case ARM::MVE_SQSHL:969  case ARM::MVE_SRSHR:970  case ARM::MVE_UQSHL:971  case ARM::MVE_URSHR:972  case ARM::MVE_SQRSHR:973  case ARM::MVE_UQRSHL:974  case ARM::MVE_ASRLr:975  case ARM::MVE_ASRLi:976  case ARM::MVE_LSLLr:977  case ARM::MVE_LSLLi:978  case ARM::MVE_LSRL:979  case ARM::MVE_SQRSHRL:980  case ARM::MVE_SQSHLL:981  case ARM::MVE_SRSHRL:982  case ARM::MVE_UQRSHLL:983  case ARM::MVE_UQSHLL:984  case ARM::MVE_URSHRL:985    return false;986  }987  const MCInstrDesc &MCID = MI->getDesc();988  uint64_t Flags = MCID.TSFlags;989  return (Flags & ARMII::DomainMask) == ARMII::DomainMVE;990}991 992} // end namespace llvm993 994#endif // LLVM_LIB_TARGET_ARM_ARMBASEINSTRINFO_H995