Path: blob/main/contrib/llvm-project/llvm/lib/Target/AArch64/AArch64InstrInfo.h
35269 views
//===- AArch64InstrInfo.h - AArch64 Instruction Information -----*- C++ -*-===//1//2// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.3// See https://llvm.org/LICENSE.txt for license information.4// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception5//6//===----------------------------------------------------------------------===//7//8// This file contains the AArch64 implementation of the TargetInstrInfo class.9//10//===----------------------------------------------------------------------===//1112#ifndef LLVM_LIB_TARGET_AARCH64_AARCH64INSTRINFO_H13#define LLVM_LIB_TARGET_AARCH64_AARCH64INSTRINFO_H1415#include "AArch64.h"16#include "AArch64RegisterInfo.h"17#include "llvm/CodeGen/TargetInstrInfo.h"18#include "llvm/Support/TypeSize.h"19#include <optional>2021#define GET_INSTRINFO_HEADER22#include "AArch64GenInstrInfo.inc"2324namespace llvm {2526class AArch64Subtarget;2728static const MachineMemOperand::Flags MOSuppressPair =29MachineMemOperand::MOTargetFlag1;30static const MachineMemOperand::Flags MOStridedAccess =31MachineMemOperand::MOTargetFlag2;3233#define FALKOR_STRIDED_ACCESS_MD "falkor.strided.access"3435// AArch64 MachineCombiner patterns36enum AArch64MachineCombinerPattern : unsigned {37// These are patterns used to reduce the length of dependence chain.38SUBADD_OP1 = MachineCombinerPattern::TARGET_PATTERN_START,39SUBADD_OP2,4041// These are multiply-add patterns matched by the AArch64 machine combiner.42MULADDW_OP1,43MULADDW_OP2,44MULSUBW_OP1,45MULSUBW_OP2,46MULADDWI_OP1,47MULSUBWI_OP1,48MULADDX_OP1,49MULADDX_OP2,50MULSUBX_OP1,51MULSUBX_OP2,52MULADDXI_OP1,53MULSUBXI_OP1,54// NEON integers vectors55MULADDv8i8_OP1,56MULADDv8i8_OP2,57MULADDv16i8_OP1,58MULADDv16i8_OP2,59MULADDv4i16_OP1,60MULADDv4i16_OP2,61MULADDv8i16_OP1,62MULADDv8i16_OP2,63MULADDv2i32_OP1,64MULADDv2i32_OP2,65MULADDv4i32_OP1,66MULADDv4i32_OP2,6768MULSUBv8i8_OP1,69MULSUBv8i8_OP2,70MULSUBv16i8_OP1,71MULSUBv16i8_OP2,72MULSUBv4i16_OP1,73MULSUBv4i16_OP2,74MULSUBv8i16_OP1,75MULSUBv8i16_OP2,76MULSUBv2i32_OP1,77MULSUBv2i32_OP2,78MULSUBv4i32_OP1,79MULSUBv4i32_OP2,8081MULADDv4i16_indexed_OP1,82MULADDv4i16_indexed_OP2,83MULADDv8i16_indexed_OP1,84MULADDv8i16_indexed_OP2,85MULADDv2i32_indexed_OP1,86MULADDv2i32_indexed_OP2,87MULADDv4i32_indexed_OP1,88MULADDv4i32_indexed_OP2,8990MULSUBv4i16_indexed_OP1,91MULSUBv4i16_indexed_OP2,92MULSUBv8i16_indexed_OP1,93MULSUBv8i16_indexed_OP2,94MULSUBv2i32_indexed_OP1,95MULSUBv2i32_indexed_OP2,96MULSUBv4i32_indexed_OP1,97MULSUBv4i32_indexed_OP2,9899// Floating Point100FMULADDH_OP1,101FMULADDH_OP2,102FMULSUBH_OP1,103FMULSUBH_OP2,104FMULADDS_OP1,105FMULADDS_OP2,106FMULSUBS_OP1,107FMULSUBS_OP2,108FMULADDD_OP1,109FMULADDD_OP2,110FMULSUBD_OP1,111FMULSUBD_OP2,112FNMULSUBH_OP1,113FNMULSUBS_OP1,114FNMULSUBD_OP1,115FMLAv1i32_indexed_OP1,116FMLAv1i32_indexed_OP2,117FMLAv1i64_indexed_OP1,118FMLAv1i64_indexed_OP2,119FMLAv4f16_OP1,120FMLAv4f16_OP2,121FMLAv8f16_OP1,122FMLAv8f16_OP2,123FMLAv2f32_OP2,124FMLAv2f32_OP1,125FMLAv2f64_OP1,126FMLAv2f64_OP2,127FMLAv4i16_indexed_OP1,128FMLAv4i16_indexed_OP2,129FMLAv8i16_indexed_OP1,130FMLAv8i16_indexed_OP2,131FMLAv2i32_indexed_OP1,132FMLAv2i32_indexed_OP2,133FMLAv2i64_indexed_OP1,134FMLAv2i64_indexed_OP2,135FMLAv4f32_OP1,136FMLAv4f32_OP2,137FMLAv4i32_indexed_OP1,138FMLAv4i32_indexed_OP2,139FMLSv1i32_indexed_OP2,140FMLSv1i64_indexed_OP2,141FMLSv4f16_OP1,142FMLSv4f16_OP2,143FMLSv8f16_OP1,144FMLSv8f16_OP2,145FMLSv2f32_OP1,146FMLSv2f32_OP2,147FMLSv2f64_OP1,148FMLSv2f64_OP2,149FMLSv4i16_indexed_OP1,150FMLSv4i16_indexed_OP2,151FMLSv8i16_indexed_OP1,152FMLSv8i16_indexed_OP2,153FMLSv2i32_indexed_OP1,154FMLSv2i32_indexed_OP2,155FMLSv2i64_indexed_OP1,156FMLSv2i64_indexed_OP2,157FMLSv4f32_OP1,158FMLSv4f32_OP2,159FMLSv4i32_indexed_OP1,160FMLSv4i32_indexed_OP2,161162FMULv2i32_indexed_OP1,163FMULv2i32_indexed_OP2,164FMULv2i64_indexed_OP1,165FMULv2i64_indexed_OP2,166FMULv4i16_indexed_OP1,167FMULv4i16_indexed_OP2,168FMULv4i32_indexed_OP1,169FMULv4i32_indexed_OP2,170FMULv8i16_indexed_OP1,171FMULv8i16_indexed_OP2,172173FNMADD,174};175class AArch64InstrInfo final : public AArch64GenInstrInfo {176const AArch64RegisterInfo RI;177const AArch64Subtarget &Subtarget;178179public:180explicit AArch64InstrInfo(const AArch64Subtarget &STI);181182/// getRegisterInfo - TargetInstrInfo is a superset of MRegister info. As183/// such, whenever a client has an instance of instruction info, it should184/// always be able to get register info as well (through this method).185const AArch64RegisterInfo &getRegisterInfo() const { return RI; }186187unsigned getInstSizeInBytes(const MachineInstr &MI) const override;188189bool isAsCheapAsAMove(const MachineInstr &MI) const override;190191bool isCoalescableExtInstr(const MachineInstr &MI, Register &SrcReg,192Register &DstReg, unsigned &SubIdx) const override;193194bool195areMemAccessesTriviallyDisjoint(const MachineInstr &MIa,196const MachineInstr &MIb) const override;197198Register isLoadFromStackSlot(const MachineInstr &MI,199int &FrameIndex) const override;200Register isStoreToStackSlot(const MachineInstr &MI,201int &FrameIndex) const override;202203/// Does this instruction set its full destination register to zero?204static bool isGPRZero(const MachineInstr &MI);205206/// Does this instruction rename a GPR without modifying bits?207static bool isGPRCopy(const MachineInstr &MI);208209/// Does this instruction rename an FPR without modifying bits?210static bool isFPRCopy(const MachineInstr &MI);211212/// Return true if pairing the given load or store is hinted to be213/// unprofitable.214static bool isLdStPairSuppressed(const MachineInstr &MI);215216/// Return true if the given load or store is a strided memory access.217static bool isStridedAccess(const MachineInstr &MI);218219/// Return true if it has an unscaled load/store offset.220static bool hasUnscaledLdStOffset(unsigned Opc);221static bool hasUnscaledLdStOffset(MachineInstr &MI) {222return hasUnscaledLdStOffset(MI.getOpcode());223}224225/// Returns the unscaled load/store for the scaled load/store opcode,226/// if there is a corresponding unscaled variant available.227static std::optional<unsigned> getUnscaledLdSt(unsigned Opc);228229/// Scaling factor for (scaled or unscaled) load or store.230static int getMemScale(unsigned Opc);231static int getMemScale(const MachineInstr &MI) {232return getMemScale(MI.getOpcode());233}234235/// Returns whether the instruction is a pre-indexed load.236static bool isPreLd(const MachineInstr &MI);237238/// Returns whether the instruction is a pre-indexed store.239static bool isPreSt(const MachineInstr &MI);240241/// Returns whether the instruction is a pre-indexed load/store.242static bool isPreLdSt(const MachineInstr &MI);243244/// Returns whether the instruction is a paired load/store.245static bool isPairedLdSt(const MachineInstr &MI);246247/// Returns the base register operator of a load/store.248static const MachineOperand &getLdStBaseOp(const MachineInstr &MI);249250/// Returns the immediate offset operator of a load/store.251static const MachineOperand &getLdStOffsetOp(const MachineInstr &MI);252253/// Returns whether the physical register is FP or NEON.254static bool isFpOrNEON(Register Reg);255256/// Returns whether the instruction is FP or NEON.257static bool isFpOrNEON(const MachineInstr &MI);258259/// Returns whether the instruction is in H form (16 bit operands)260static bool isHForm(const MachineInstr &MI);261262/// Returns whether the instruction is in Q form (128 bit operands)263static bool isQForm(const MachineInstr &MI);264265/// Returns whether the instruction can be compatible with non-zero BTYPE.266static bool hasBTISemantics(const MachineInstr &MI);267268/// Returns the index for the immediate for a given instruction.269static unsigned getLoadStoreImmIdx(unsigned Opc);270271/// Return true if pairing the given load or store may be paired with another.272static bool isPairableLdStInst(const MachineInstr &MI);273274/// Returns true if MI is one of the TCRETURN* instructions.275static bool isTailCallReturnInst(const MachineInstr &MI);276277/// Return the opcode that set flags when possible. The caller is278/// responsible for ensuring the opc has a flag setting equivalent.279static unsigned convertToFlagSettingOpc(unsigned Opc);280281/// Return true if this is a load/store that can be potentially paired/merged.282bool isCandidateToMergeOrPair(const MachineInstr &MI) const;283284/// Hint that pairing the given load or store is unprofitable.285static void suppressLdStPair(MachineInstr &MI);286287std::optional<ExtAddrMode>288getAddrModeFromMemoryOp(const MachineInstr &MemI,289const TargetRegisterInfo *TRI) const override;290291bool canFoldIntoAddrMode(const MachineInstr &MemI, Register Reg,292const MachineInstr &AddrI,293ExtAddrMode &AM) const override;294295MachineInstr *emitLdStWithAddr(MachineInstr &MemI,296const ExtAddrMode &AM) const override;297298bool getMemOperandsWithOffsetWidth(299const MachineInstr &MI, SmallVectorImpl<const MachineOperand *> &BaseOps,300int64_t &Offset, bool &OffsetIsScalable, LocationSize &Width,301const TargetRegisterInfo *TRI) const override;302303/// If \p OffsetIsScalable is set to 'true', the offset is scaled by `vscale`.304/// This is true for some SVE instructions like ldr/str that have a305/// 'reg + imm' addressing mode where the immediate is an index to the306/// scalable vector located at 'reg + imm * vscale x #bytes'.307bool getMemOperandWithOffsetWidth(const MachineInstr &MI,308const MachineOperand *&BaseOp,309int64_t &Offset, bool &OffsetIsScalable,310TypeSize &Width,311const TargetRegisterInfo *TRI) const;312313/// Return the immediate offset of the base register in a load/store \p LdSt.314MachineOperand &getMemOpBaseRegImmOfsOffsetOperand(MachineInstr &LdSt) const;315316/// Returns true if opcode \p Opc is a memory operation. If it is, set317/// \p Scale, \p Width, \p MinOffset, and \p MaxOffset accordingly.318///319/// For unscaled instructions, \p Scale is set to 1.320static bool getMemOpInfo(unsigned Opcode, TypeSize &Scale, TypeSize &Width,321int64_t &MinOffset, int64_t &MaxOffset);322323bool shouldClusterMemOps(ArrayRef<const MachineOperand *> BaseOps1,324int64_t Offset1, bool OffsetIsScalable1,325ArrayRef<const MachineOperand *> BaseOps2,326int64_t Offset2, bool OffsetIsScalable2,327unsigned ClusterSize,328unsigned NumBytes) const override;329330void copyPhysRegTuple(MachineBasicBlock &MBB, MachineBasicBlock::iterator I,331const DebugLoc &DL, MCRegister DestReg,332MCRegister SrcReg, bool KillSrc, unsigned Opcode,333llvm::ArrayRef<unsigned> Indices) const;334void copyGPRRegTuple(MachineBasicBlock &MBB, MachineBasicBlock::iterator I,335DebugLoc DL, unsigned DestReg, unsigned SrcReg,336bool KillSrc, unsigned Opcode, unsigned ZeroReg,337llvm::ArrayRef<unsigned> Indices) const;338void copyPhysReg(MachineBasicBlock &MBB, MachineBasicBlock::iterator I,339const DebugLoc &DL, MCRegister DestReg, MCRegister SrcReg,340bool KillSrc) const override;341342void storeRegToStackSlot(MachineBasicBlock &MBB,343MachineBasicBlock::iterator MBBI, Register SrcReg,344bool isKill, int FrameIndex,345const TargetRegisterClass *RC,346const TargetRegisterInfo *TRI,347Register VReg) const override;348349void loadRegFromStackSlot(MachineBasicBlock &MBB,350MachineBasicBlock::iterator MBBI, Register DestReg,351int FrameIndex, const TargetRegisterClass *RC,352const TargetRegisterInfo *TRI,353Register VReg) const override;354355// This tells target independent code that it is okay to pass instructions356// with subreg operands to foldMemoryOperandImpl.357bool isSubregFoldable() const override { return true; }358359using TargetInstrInfo::foldMemoryOperandImpl;360MachineInstr *361foldMemoryOperandImpl(MachineFunction &MF, MachineInstr &MI,362ArrayRef<unsigned> Ops,363MachineBasicBlock::iterator InsertPt, int FrameIndex,364LiveIntervals *LIS = nullptr,365VirtRegMap *VRM = nullptr) const override;366367/// \returns true if a branch from an instruction with opcode \p BranchOpc368/// bytes is capable of jumping to a position \p BrOffset bytes away.369bool isBranchOffsetInRange(unsigned BranchOpc,370int64_t BrOffset) const override;371372MachineBasicBlock *getBranchDestBlock(const MachineInstr &MI) const override;373374void insertIndirectBranch(MachineBasicBlock &MBB,375MachineBasicBlock &NewDestBB,376MachineBasicBlock &RestoreBB, const DebugLoc &DL,377int64_t BrOffset, RegScavenger *RS) const override;378379bool analyzeBranch(MachineBasicBlock &MBB, MachineBasicBlock *&TBB,380MachineBasicBlock *&FBB,381SmallVectorImpl<MachineOperand> &Cond,382bool AllowModify = false) const override;383bool analyzeBranchPredicate(MachineBasicBlock &MBB,384MachineBranchPredicate &MBP,385bool AllowModify) const override;386unsigned removeBranch(MachineBasicBlock &MBB,387int *BytesRemoved = nullptr) const override;388unsigned insertBranch(MachineBasicBlock &MBB, MachineBasicBlock *TBB,389MachineBasicBlock *FBB, ArrayRef<MachineOperand> Cond,390const DebugLoc &DL,391int *BytesAdded = nullptr) const override;392393std::unique_ptr<TargetInstrInfo::PipelinerLoopInfo>394analyzeLoopForPipelining(MachineBasicBlock *LoopBB) const override;395396bool397reverseBranchCondition(SmallVectorImpl<MachineOperand> &Cond) const override;398bool canInsertSelect(const MachineBasicBlock &, ArrayRef<MachineOperand> Cond,399Register, Register, Register, int &, int &,400int &) const override;401void insertSelect(MachineBasicBlock &MBB, MachineBasicBlock::iterator MI,402const DebugLoc &DL, Register DstReg,403ArrayRef<MachineOperand> Cond, Register TrueReg,404Register FalseReg) const override;405406void insertNoop(MachineBasicBlock &MBB,407MachineBasicBlock::iterator MI) const override;408409MCInst getNop() const override;410411bool isSchedulingBoundary(const MachineInstr &MI,412const MachineBasicBlock *MBB,413const MachineFunction &MF) const override;414415/// analyzeCompare - For a comparison instruction, return the source registers416/// in SrcReg and SrcReg2, and the value it compares against in CmpValue.417/// Return true if the comparison instruction can be analyzed.418bool analyzeCompare(const MachineInstr &MI, Register &SrcReg,419Register &SrcReg2, int64_t &CmpMask,420int64_t &CmpValue) const override;421/// optimizeCompareInstr - Convert the instruction supplying the argument to422/// the comparison into one that sets the zero bit in the flags register.423bool optimizeCompareInstr(MachineInstr &CmpInstr, Register SrcReg,424Register SrcReg2, int64_t CmpMask, int64_t CmpValue,425const MachineRegisterInfo *MRI) const override;426bool optimizeCondBranch(MachineInstr &MI) const override;427428CombinerObjective getCombinerObjective(unsigned Pattern) const override;429/// Return true when a code sequence can improve throughput. It430/// should be called only for instructions in loops.431/// \param Pattern - combiner pattern432bool isThroughputPattern(unsigned Pattern) const override;433/// Return true when there is potentially a faster code sequence434/// for an instruction chain ending in ``Root``. All potential patterns are435/// listed in the ``Patterns`` array.436bool getMachineCombinerPatterns(MachineInstr &Root,437SmallVectorImpl<unsigned> &Patterns,438bool DoRegPressureReduce) const override;439/// Return true when Inst is associative and commutative so that it can be440/// reassociated. If Invert is true, then the inverse of Inst operation must441/// be checked.442bool isAssociativeAndCommutative(const MachineInstr &Inst,443bool Invert) const override;444/// When getMachineCombinerPatterns() finds patterns, this function generates445/// the instructions that could replace the original code sequence446void genAlternativeCodeSequence(447MachineInstr &Root, unsigned Pattern,448SmallVectorImpl<MachineInstr *> &InsInstrs,449SmallVectorImpl<MachineInstr *> &DelInstrs,450DenseMap<unsigned, unsigned> &InstrIdxForVirtReg) const override;451/// AArch64 supports MachineCombiner.452bool useMachineCombiner() const override;453454bool expandPostRAPseudo(MachineInstr &MI) const override;455456std::pair<unsigned, unsigned>457decomposeMachineOperandsTargetFlags(unsigned TF) const override;458ArrayRef<std::pair<unsigned, const char *>>459getSerializableDirectMachineOperandTargetFlags() const override;460ArrayRef<std::pair<unsigned, const char *>>461getSerializableBitmaskMachineOperandTargetFlags() const override;462ArrayRef<std::pair<MachineMemOperand::Flags, const char *>>463getSerializableMachineMemOperandTargetFlags() const override;464465bool isFunctionSafeToOutlineFrom(MachineFunction &MF,466bool OutlineFromLinkOnceODRs) const override;467std::optional<outliner::OutlinedFunction> getOutliningCandidateInfo(468std::vector<outliner::Candidate> &RepeatedSequenceLocs) const override;469void mergeOutliningCandidateAttributes(470Function &F, std::vector<outliner::Candidate> &Candidates) const override;471outliner::InstrType472getOutliningTypeImpl(MachineBasicBlock::iterator &MIT, unsigned Flags) const override;473SmallVector<474std::pair<MachineBasicBlock::iterator, MachineBasicBlock::iterator>>475getOutlinableRanges(MachineBasicBlock &MBB, unsigned &Flags) const override;476void buildOutlinedFrame(MachineBasicBlock &MBB, MachineFunction &MF,477const outliner::OutlinedFunction &OF) const override;478MachineBasicBlock::iterator479insertOutlinedCall(Module &M, MachineBasicBlock &MBB,480MachineBasicBlock::iterator &It, MachineFunction &MF,481outliner::Candidate &C) const override;482bool shouldOutlineFromFunctionByDefault(MachineFunction &MF) const override;483484void buildClearRegister(Register Reg, MachineBasicBlock &MBB,485MachineBasicBlock::iterator Iter, DebugLoc &DL,486bool AllowSideEffects = true) const override;487488/// Returns the vector element size (B, H, S or D) of an SVE opcode.489uint64_t getElementSizeForOpcode(unsigned Opc) const;490/// Returns true if the opcode is for an SVE instruction that sets the491/// condition codes as if it's results had been fed to a PTEST instruction492/// along with the same general predicate.493bool isPTestLikeOpcode(unsigned Opc) const;494/// Returns true if the opcode is for an SVE WHILE## instruction.495bool isWhileOpcode(unsigned Opc) const;496/// Returns true if the instruction has a shift by immediate that can be497/// executed in one cycle less.498static bool isFalkorShiftExtFast(const MachineInstr &MI);499/// Return true if the instructions is a SEH instruciton used for unwinding500/// on Windows.501static bool isSEHInstruction(const MachineInstr &MI);502503std::optional<RegImmPair> isAddImmediate(const MachineInstr &MI,504Register Reg) const override;505506bool isFunctionSafeToSplit(const MachineFunction &MF) const override;507508bool isMBBSafeToSplitToCold(const MachineBasicBlock &MBB) const override;509510std::optional<ParamLoadedValue>511describeLoadedValue(const MachineInstr &MI, Register Reg) const override;512513unsigned int getTailDuplicateSize(CodeGenOptLevel OptLevel) const override;514515bool isExtendLikelyToBeFolded(MachineInstr &ExtMI,516MachineRegisterInfo &MRI) const override;517518static void decomposeStackOffsetForFrameOffsets(const StackOffset &Offset,519int64_t &NumBytes,520int64_t &NumPredicateVectors,521int64_t &NumDataVectors);522static void decomposeStackOffsetForDwarfOffsets(const StackOffset &Offset,523int64_t &ByteSized,524int64_t &VGSized);525526// Return true if address of the form BaseReg + Scale * ScaledReg + Offset can527// be used for a load/store of NumBytes. BaseReg is always present and528// implicit.529bool isLegalAddressingMode(unsigned NumBytes, int64_t Offset,530unsigned Scale) const;531532// Decrement the SP, issuing probes along the way. `TargetReg` is the new top533// of the stack. `FrameSetup` is passed as true, if the allocation is a part534// of constructing the activation frame of a function.535MachineBasicBlock::iterator probedStackAlloc(MachineBasicBlock::iterator MBBI,536Register TargetReg,537bool FrameSetup) const;538539#define GET_INSTRINFO_HELPER_DECLS540#include "AArch64GenInstrInfo.inc"541542protected:543/// If the specific machine instruction is an instruction that moves/copies544/// value from one register to another register return destination and source545/// registers as machine operands.546std::optional<DestSourcePair>547isCopyInstrImpl(const MachineInstr &MI) const override;548std::optional<DestSourcePair>549isCopyLikeInstrImpl(const MachineInstr &MI) const override;550551private:552unsigned getInstBundleLength(const MachineInstr &MI) const;553554/// Sets the offsets on outlined instructions in \p MBB which use SP555/// so that they will be valid post-outlining.556///557/// \param MBB A \p MachineBasicBlock in an outlined function.558void fixupPostOutline(MachineBasicBlock &MBB) const;559560void instantiateCondBranch(MachineBasicBlock &MBB, const DebugLoc &DL,561MachineBasicBlock *TBB,562ArrayRef<MachineOperand> Cond) const;563bool substituteCmpToZero(MachineInstr &CmpInstr, unsigned SrcReg,564const MachineRegisterInfo &MRI) const;565bool removeCmpToZeroOrOne(MachineInstr &CmpInstr, unsigned SrcReg,566int CmpValue, const MachineRegisterInfo &MRI) const;567568/// Returns an unused general-purpose register which can be used for569/// constructing an outlined call if one exists. Returns 0 otherwise.570Register findRegisterToSaveLRTo(outliner::Candidate &C) const;571572/// Remove a ptest of a predicate-generating operation that already sets, or573/// can be made to set, the condition codes in an identical manner574bool optimizePTestInstr(MachineInstr *PTest, unsigned MaskReg,575unsigned PredReg,576const MachineRegisterInfo *MRI) const;577std::optional<unsigned>578canRemovePTestInstr(MachineInstr *PTest, MachineInstr *Mask,579MachineInstr *Pred, const MachineRegisterInfo *MRI) const;580};581582struct UsedNZCV {583bool N = false;584bool Z = false;585bool C = false;586bool V = false;587588UsedNZCV() = default;589590UsedNZCV &operator|=(const UsedNZCV &UsedFlags) {591this->N |= UsedFlags.N;592this->Z |= UsedFlags.Z;593this->C |= UsedFlags.C;594this->V |= UsedFlags.V;595return *this;596}597};598599/// \returns Conditions flags used after \p CmpInstr in its MachineBB if NZCV600/// flags are not alive in successors of the same \p CmpInstr and \p MI parent.601/// \returns std::nullopt otherwise.602///603/// Collect instructions using that flags in \p CCUseInstrs if provided.604std::optional<UsedNZCV>605examineCFlagsUse(MachineInstr &MI, MachineInstr &CmpInstr,606const TargetRegisterInfo &TRI,607SmallVectorImpl<MachineInstr *> *CCUseInstrs = nullptr);608609/// Return true if there is an instruction /after/ \p DefMI and before \p UseMI610/// which either reads or clobbers NZCV.611bool isNZCVTouchedInInstructionRange(const MachineInstr &DefMI,612const MachineInstr &UseMI,613const TargetRegisterInfo *TRI);614615MCCFIInstruction createDefCFA(const TargetRegisterInfo &TRI, unsigned FrameReg,616unsigned Reg, const StackOffset &Offset,617bool LastAdjustmentWasScalable = true);618MCCFIInstruction createCFAOffset(const TargetRegisterInfo &MRI, unsigned Reg,619const StackOffset &OffsetFromDefCFA);620621/// emitFrameOffset - Emit instructions as needed to set DestReg to SrcReg622/// plus Offset. This is intended to be used from within the prolog/epilog623/// insertion (PEI) pass, where a virtual scratch register may be allocated624/// if necessary, to be replaced by the scavenger at the end of PEI.625void emitFrameOffset(MachineBasicBlock &MBB, MachineBasicBlock::iterator MBBI,626const DebugLoc &DL, unsigned DestReg, unsigned SrcReg,627StackOffset Offset, const TargetInstrInfo *TII,628MachineInstr::MIFlag = MachineInstr::NoFlags,629bool SetNZCV = false, bool NeedsWinCFI = false,630bool *HasWinCFI = nullptr, bool EmitCFAOffset = false,631StackOffset InitialOffset = {},632unsigned FrameReg = AArch64::SP);633634/// rewriteAArch64FrameIndex - Rewrite MI to access 'Offset' bytes from the635/// FP. Return false if the offset could not be handled directly in MI, and636/// return the left-over portion by reference.637bool rewriteAArch64FrameIndex(MachineInstr &MI, unsigned FrameRegIdx,638unsigned FrameReg, StackOffset &Offset,639const AArch64InstrInfo *TII);640641/// Use to report the frame offset status in isAArch64FrameOffsetLegal.642enum AArch64FrameOffsetStatus {643AArch64FrameOffsetCannotUpdate = 0x0, ///< Offset cannot apply.644AArch64FrameOffsetIsLegal = 0x1, ///< Offset is legal.645AArch64FrameOffsetCanUpdate = 0x2 ///< Offset can apply, at least partly.646};647648/// Check if the @p Offset is a valid frame offset for @p MI.649/// The returned value reports the validity of the frame offset for @p MI.650/// It uses the values defined by AArch64FrameOffsetStatus for that.651/// If result == AArch64FrameOffsetCannotUpdate, @p MI cannot be updated to652/// use an offset.eq653/// If result & AArch64FrameOffsetIsLegal, @p Offset can completely be654/// rewritten in @p MI.655/// If result & AArch64FrameOffsetCanUpdate, @p Offset contains the656/// amount that is off the limit of the legal offset.657/// If set, @p OutUseUnscaledOp will contain the whether @p MI should be658/// turned into an unscaled operator, which opcode is in @p OutUnscaledOp.659/// If set, @p EmittableOffset contains the amount that can be set in @p MI660/// (possibly with @p OutUnscaledOp if OutUseUnscaledOp is true) and that661/// is a legal offset.662int isAArch64FrameOffsetLegal(const MachineInstr &MI, StackOffset &Offset,663bool *OutUseUnscaledOp = nullptr,664unsigned *OutUnscaledOp = nullptr,665int64_t *EmittableOffset = nullptr);666667static inline bool isUncondBranchOpcode(int Opc) { return Opc == AArch64::B; }668669static inline bool isCondBranchOpcode(int Opc) {670switch (Opc) {671case AArch64::Bcc:672case AArch64::CBZW:673case AArch64::CBZX:674case AArch64::CBNZW:675case AArch64::CBNZX:676case AArch64::TBZW:677case AArch64::TBZX:678case AArch64::TBNZW:679case AArch64::TBNZX:680return true;681default:682return false;683}684}685686static inline bool isIndirectBranchOpcode(int Opc) {687switch (Opc) {688case AArch64::BR:689case AArch64::BRAA:690case AArch64::BRAB:691case AArch64::BRAAZ:692case AArch64::BRABZ:693return true;694}695return false;696}697698static inline bool isPTrueOpcode(unsigned Opc) {699switch (Opc) {700case AArch64::PTRUE_B:701case AArch64::PTRUE_H:702case AArch64::PTRUE_S:703case AArch64::PTRUE_D:704return true;705default:706return false;707}708}709710/// Return opcode to be used for indirect calls.711unsigned getBLRCallOpcode(const MachineFunction &MF);712713/// Return XPAC opcode to be used for a ptrauth strip using the given key.714static inline unsigned getXPACOpcodeForKey(AArch64PACKey::ID K) {715using namespace AArch64PACKey;716switch (K) {717case IA: case IB: return AArch64::XPACI;718case DA: case DB: return AArch64::XPACD;719}720llvm_unreachable("Unhandled AArch64PACKey::ID enum");721}722723/// Return AUT opcode to be used for a ptrauth auth using the given key, or its724/// AUT*Z variant that doesn't take a discriminator operand, using zero instead.725static inline unsigned getAUTOpcodeForKey(AArch64PACKey::ID K, bool Zero) {726using namespace AArch64PACKey;727switch (K) {728case IA: return Zero ? AArch64::AUTIZA : AArch64::AUTIA;729case IB: return Zero ? AArch64::AUTIZB : AArch64::AUTIB;730case DA: return Zero ? AArch64::AUTDZA : AArch64::AUTDA;731case DB: return Zero ? AArch64::AUTDZB : AArch64::AUTDB;732}733llvm_unreachable("Unhandled AArch64PACKey::ID enum");734}735736/// Return PAC opcode to be used for a ptrauth sign using the given key, or its737/// PAC*Z variant that doesn't take a discriminator operand, using zero instead.738static inline unsigned getPACOpcodeForKey(AArch64PACKey::ID K, bool Zero) {739using namespace AArch64PACKey;740switch (K) {741case IA: return Zero ? AArch64::PACIZA : AArch64::PACIA;742case IB: return Zero ? AArch64::PACIZB : AArch64::PACIB;743case DA: return Zero ? AArch64::PACDZA : AArch64::PACDA;744case DB: return Zero ? AArch64::PACDZB : AArch64::PACDB;745}746llvm_unreachable("Unhandled AArch64PACKey::ID enum");747}748749// struct TSFlags {750#define TSFLAG_ELEMENT_SIZE_TYPE(X) (X) // 3-bits751#define TSFLAG_DESTRUCTIVE_INST_TYPE(X) ((X) << 3) // 4-bits752#define TSFLAG_FALSE_LANE_TYPE(X) ((X) << 7) // 2-bits753#define TSFLAG_INSTR_FLAGS(X) ((X) << 9) // 2-bits754#define TSFLAG_SME_MATRIX_TYPE(X) ((X) << 11) // 3-bits755// }756757namespace AArch64 {758759enum ElementSizeType {760ElementSizeMask = TSFLAG_ELEMENT_SIZE_TYPE(0x7),761ElementSizeNone = TSFLAG_ELEMENT_SIZE_TYPE(0x0),762ElementSizeB = TSFLAG_ELEMENT_SIZE_TYPE(0x1),763ElementSizeH = TSFLAG_ELEMENT_SIZE_TYPE(0x2),764ElementSizeS = TSFLAG_ELEMENT_SIZE_TYPE(0x3),765ElementSizeD = TSFLAG_ELEMENT_SIZE_TYPE(0x4),766};767768enum DestructiveInstType {769DestructiveInstTypeMask = TSFLAG_DESTRUCTIVE_INST_TYPE(0xf),770NotDestructive = TSFLAG_DESTRUCTIVE_INST_TYPE(0x0),771DestructiveOther = TSFLAG_DESTRUCTIVE_INST_TYPE(0x1),772DestructiveUnary = TSFLAG_DESTRUCTIVE_INST_TYPE(0x2),773DestructiveBinaryImm = TSFLAG_DESTRUCTIVE_INST_TYPE(0x3),774DestructiveBinaryShImmUnpred = TSFLAG_DESTRUCTIVE_INST_TYPE(0x4),775DestructiveBinary = TSFLAG_DESTRUCTIVE_INST_TYPE(0x5),776DestructiveBinaryComm = TSFLAG_DESTRUCTIVE_INST_TYPE(0x6),777DestructiveBinaryCommWithRev = TSFLAG_DESTRUCTIVE_INST_TYPE(0x7),778DestructiveTernaryCommWithRev = TSFLAG_DESTRUCTIVE_INST_TYPE(0x8),779DestructiveUnaryPassthru = TSFLAG_DESTRUCTIVE_INST_TYPE(0x9),780};781782enum FalseLaneType {783FalseLanesMask = TSFLAG_FALSE_LANE_TYPE(0x3),784FalseLanesZero = TSFLAG_FALSE_LANE_TYPE(0x1),785FalseLanesUndef = TSFLAG_FALSE_LANE_TYPE(0x2),786};787788// NOTE: This is a bit field.789static const uint64_t InstrFlagIsWhile = TSFLAG_INSTR_FLAGS(0x1);790static const uint64_t InstrFlagIsPTestLike = TSFLAG_INSTR_FLAGS(0x2);791792enum SMEMatrixType {793SMEMatrixTypeMask = TSFLAG_SME_MATRIX_TYPE(0x7),794SMEMatrixNone = TSFLAG_SME_MATRIX_TYPE(0x0),795SMEMatrixTileB = TSFLAG_SME_MATRIX_TYPE(0x1),796SMEMatrixTileH = TSFLAG_SME_MATRIX_TYPE(0x2),797SMEMatrixTileS = TSFLAG_SME_MATRIX_TYPE(0x3),798SMEMatrixTileD = TSFLAG_SME_MATRIX_TYPE(0x4),799SMEMatrixTileQ = TSFLAG_SME_MATRIX_TYPE(0x5),800SMEMatrixArray = TSFLAG_SME_MATRIX_TYPE(0x6),801};802803#undef TSFLAG_ELEMENT_SIZE_TYPE804#undef TSFLAG_DESTRUCTIVE_INST_TYPE805#undef TSFLAG_FALSE_LANE_TYPE806#undef TSFLAG_INSTR_FLAGS807#undef TSFLAG_SME_MATRIX_TYPE808809int getSVEPseudoMap(uint16_t Opcode);810int getSVERevInstr(uint16_t Opcode);811int getSVENonRevInstr(uint16_t Opcode);812813int getSMEPseudoMap(uint16_t Opcode);814}815816} // end namespace llvm817818#endif819820821