xref: /freebsd/contrib/llvm-project/llvm/lib/Target/Hexagon/HexagonInstrInfo.h (revision 0fca6ea1d4eea4c934cfff25ac9ee8ad6fe95583)
10b57cec5SDimitry Andric //===- HexagonInstrInfo.h - Hexagon Instruction Information -----*- C++ -*-===//
20b57cec5SDimitry Andric //
30b57cec5SDimitry Andric // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
40b57cec5SDimitry Andric // See https://llvm.org/LICENSE.txt for license information.
50b57cec5SDimitry Andric // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
60b57cec5SDimitry Andric //
70b57cec5SDimitry Andric //===----------------------------------------------------------------------===//
80b57cec5SDimitry Andric //
90b57cec5SDimitry Andric // This file contains the Hexagon implementation of the TargetInstrInfo class.
100b57cec5SDimitry Andric //
110b57cec5SDimitry Andric //===----------------------------------------------------------------------===//
120b57cec5SDimitry Andric 
130b57cec5SDimitry Andric #ifndef LLVM_LIB_TARGET_HEXAGON_HEXAGONINSTRINFO_H
140b57cec5SDimitry Andric #define LLVM_LIB_TARGET_HEXAGON_HEXAGONINSTRINFO_H
150b57cec5SDimitry Andric 
160b57cec5SDimitry Andric #include "MCTargetDesc/HexagonBaseInfo.h"
170b57cec5SDimitry Andric #include "llvm/ADT/ArrayRef.h"
180b57cec5SDimitry Andric #include "llvm/ADT/SmallVector.h"
190b57cec5SDimitry Andric #include "llvm/CodeGen/MachineBasicBlock.h"
200b57cec5SDimitry Andric #include "llvm/CodeGen/TargetInstrInfo.h"
210b57cec5SDimitry Andric #include "llvm/CodeGen/ValueTypes.h"
22*0fca6ea1SDimitry Andric #include "llvm/CodeGenTypes/MachineValueType.h"
230b57cec5SDimitry Andric #include <cstdint>
240b57cec5SDimitry Andric #include <vector>
250b57cec5SDimitry Andric 
260b57cec5SDimitry Andric #define GET_INSTRINFO_HEADER
270b57cec5SDimitry Andric #include "HexagonGenInstrInfo.inc"
280b57cec5SDimitry Andric 
290b57cec5SDimitry Andric namespace llvm {
300b57cec5SDimitry Andric 
310b57cec5SDimitry Andric class HexagonSubtarget;
320b57cec5SDimitry Andric class MachineBranchProbabilityInfo;
330b57cec5SDimitry Andric class MachineFunction;
340b57cec5SDimitry Andric class MachineInstr;
350b57cec5SDimitry Andric class MachineOperand;
360b57cec5SDimitry Andric class TargetRegisterInfo;
370b57cec5SDimitry Andric 
380b57cec5SDimitry Andric class HexagonInstrInfo : public HexagonGenInstrInfo {
390b57cec5SDimitry Andric   const HexagonSubtarget &Subtarget;
400b57cec5SDimitry Andric 
410b57cec5SDimitry Andric   enum BundleAttribute {
420b57cec5SDimitry Andric     memShufDisabledMask = 0x4
430b57cec5SDimitry Andric   };
440b57cec5SDimitry Andric 
450b57cec5SDimitry Andric   virtual void anchor();
460b57cec5SDimitry Andric 
470b57cec5SDimitry Andric public:
480b57cec5SDimitry Andric   explicit HexagonInstrInfo(HexagonSubtarget &ST);
490b57cec5SDimitry Andric 
500b57cec5SDimitry Andric   /// TargetInstrInfo overrides.
510b57cec5SDimitry Andric 
520b57cec5SDimitry Andric   /// If the specified machine instruction is a direct
530b57cec5SDimitry Andric   /// load from a stack slot, return the virtual or physical register number of
540b57cec5SDimitry Andric   /// the destination along with the FrameIndex of the loaded stack slot.  If
550b57cec5SDimitry Andric   /// not, return 0.  This predicate must return 0 if the instruction has
560b57cec5SDimitry Andric   /// any side effects other than loading from the stack slot.
57*0fca6ea1SDimitry Andric   Register isLoadFromStackSlot(const MachineInstr &MI,
580b57cec5SDimitry Andric                                int &FrameIndex) const override;
590b57cec5SDimitry Andric 
600b57cec5SDimitry Andric   /// If the specified machine instruction is a direct
610b57cec5SDimitry Andric   /// store to a stack slot, return the virtual or physical register number of
620b57cec5SDimitry Andric   /// the source reg along with the FrameIndex of the loaded stack slot.  If
630b57cec5SDimitry Andric   /// not, return 0.  This predicate must return 0 if the instruction has
640b57cec5SDimitry Andric   /// any side effects other than storing to the stack slot.
65*0fca6ea1SDimitry Andric   Register isStoreToStackSlot(const MachineInstr &MI,
660b57cec5SDimitry Andric                               int &FrameIndex) const override;
670b57cec5SDimitry Andric 
680b57cec5SDimitry Andric   /// Check if the instruction or the bundle of instructions has
690b57cec5SDimitry Andric   /// load from stack slots. Return the frameindex and machine memory operand
700b57cec5SDimitry Andric   /// if true.
710b57cec5SDimitry Andric   bool hasLoadFromStackSlot(
720b57cec5SDimitry Andric       const MachineInstr &MI,
730b57cec5SDimitry Andric       SmallVectorImpl<const MachineMemOperand *> &Accesses) const override;
740b57cec5SDimitry Andric 
750b57cec5SDimitry Andric   /// Check if the instruction or the bundle of instructions has
760b57cec5SDimitry Andric   /// store to stack slots. Return the frameindex and machine memory operand
770b57cec5SDimitry Andric   /// if true.
780b57cec5SDimitry Andric   bool hasStoreToStackSlot(
790b57cec5SDimitry Andric       const MachineInstr &MI,
800b57cec5SDimitry Andric       SmallVectorImpl<const MachineMemOperand *> &Accesses) const override;
810b57cec5SDimitry Andric 
820b57cec5SDimitry Andric   /// Analyze the branching code at the end of MBB, returning
830b57cec5SDimitry Andric   /// true if it cannot be understood (e.g. it's a switch dispatch or isn't
840b57cec5SDimitry Andric   /// implemented for a target).  Upon success, this returns false and returns
850b57cec5SDimitry Andric   /// with the following information in various cases:
860b57cec5SDimitry Andric   ///
870b57cec5SDimitry Andric   /// 1. If this block ends with no branches (it just falls through to its succ)
880b57cec5SDimitry Andric   ///    just return false, leaving TBB/FBB null.
890b57cec5SDimitry Andric   /// 2. If this block ends with only an unconditional branch, it sets TBB to be
900b57cec5SDimitry Andric   ///    the destination block.
910b57cec5SDimitry Andric   /// 3. If this block ends with a conditional branch and it falls through to a
920b57cec5SDimitry Andric   ///    successor block, it sets TBB to be the branch destination block and a
930b57cec5SDimitry Andric   ///    list of operands that evaluate the condition. These operands can be
940b57cec5SDimitry Andric   ///    passed to other TargetInstrInfo methods to create new branches.
950b57cec5SDimitry Andric   /// 4. If this block ends with a conditional branch followed by an
960b57cec5SDimitry Andric   ///    unconditional branch, it returns the 'true' destination in TBB, the
970b57cec5SDimitry Andric   ///    'false' destination in FBB, and a list of operands that evaluate the
980b57cec5SDimitry Andric   ///    condition.  These operands can be passed to other TargetInstrInfo
990b57cec5SDimitry Andric   ///    methods to create new branches.
1000b57cec5SDimitry Andric   ///
1010b57cec5SDimitry Andric   /// Note that removeBranch and insertBranch must be implemented to support
1020b57cec5SDimitry Andric   /// cases where this method returns success.
1030b57cec5SDimitry Andric   ///
1040b57cec5SDimitry Andric   /// If AllowModify is true, then this routine is allowed to modify the basic
1050b57cec5SDimitry Andric   /// block (e.g. delete instructions after the unconditional branch).
1060b57cec5SDimitry Andric   bool analyzeBranch(MachineBasicBlock &MBB, MachineBasicBlock *&TBB,
1070b57cec5SDimitry Andric                      MachineBasicBlock *&FBB,
1080b57cec5SDimitry Andric                      SmallVectorImpl<MachineOperand> &Cond,
1090b57cec5SDimitry Andric                      bool AllowModify) const override;
1100b57cec5SDimitry Andric 
1110b57cec5SDimitry Andric   /// Remove the branching code at the end of the specific MBB.
1125ffd83dbSDimitry Andric   /// This is only invoked in cases where analyzeBranch returns success. It
1130b57cec5SDimitry Andric   /// returns the number of instructions that were removed.
1140b57cec5SDimitry Andric   unsigned removeBranch(MachineBasicBlock &MBB,
1150b57cec5SDimitry Andric                         int *BytesRemoved = nullptr) const override;
1160b57cec5SDimitry Andric 
1170b57cec5SDimitry Andric   /// Insert branch code into the end of the specified MachineBasicBlock.
1180b57cec5SDimitry Andric   /// The operands to this method are the same as those
1195ffd83dbSDimitry Andric   /// returned by analyzeBranch.  This is only invoked in cases where
1205ffd83dbSDimitry Andric   /// analyzeBranch returns success. It returns the number of instructions
1210b57cec5SDimitry Andric   /// inserted.
1220b57cec5SDimitry Andric   ///
1230b57cec5SDimitry Andric   /// It is also invoked by tail merging to add unconditional branches in
1245ffd83dbSDimitry Andric   /// cases where analyzeBranch doesn't apply because there was no original
1250b57cec5SDimitry Andric   /// branch to analyze.  At least this much must be implemented, else tail
1260b57cec5SDimitry Andric   /// merging needs to be disabled.
1270b57cec5SDimitry Andric   unsigned insertBranch(MachineBasicBlock &MBB, MachineBasicBlock *TBB,
1280b57cec5SDimitry Andric                         MachineBasicBlock *FBB, ArrayRef<MachineOperand> Cond,
1290b57cec5SDimitry Andric                         const DebugLoc &DL,
1300b57cec5SDimitry Andric                         int *BytesAdded = nullptr) const override;
1310b57cec5SDimitry Andric 
1328bcb0991SDimitry Andric   /// Analyze loop L, which must be a single-basic-block loop, and if the
1338bcb0991SDimitry Andric   /// conditions can be understood enough produce a PipelinerLoopInfo object.
1348bcb0991SDimitry Andric   std::unique_ptr<PipelinerLoopInfo>
1358bcb0991SDimitry Andric   analyzeLoopForPipelining(MachineBasicBlock *LoopBB) const override;
1360b57cec5SDimitry Andric 
1370b57cec5SDimitry Andric   /// Return true if it's profitable to predicate
1380b57cec5SDimitry Andric   /// instructions with accumulated instruction latency of "NumCycles"
1390b57cec5SDimitry Andric   /// of the specified basic block, where the probability of the instructions
1400b57cec5SDimitry Andric   /// being executed is given by Probability, and Confidence is a measure
1410b57cec5SDimitry Andric   /// of our confidence that it will be properly predicted.
1420b57cec5SDimitry Andric   bool isProfitableToIfCvt(MachineBasicBlock &MBB, unsigned NumCycles,
1430b57cec5SDimitry Andric                            unsigned ExtraPredCycles,
1440b57cec5SDimitry Andric                            BranchProbability Probability) const override;
1450b57cec5SDimitry Andric 
1460b57cec5SDimitry Andric   /// Second variant of isProfitableToIfCvt. This one
1470b57cec5SDimitry Andric   /// checks for the case where two basic blocks from true and false path
1480b57cec5SDimitry Andric   /// of a if-then-else (diamond) are predicated on mutally exclusive
1490b57cec5SDimitry Andric   /// predicates, where the probability of the true path being taken is given
1500b57cec5SDimitry Andric   /// by Probability, and Confidence is a measure of our confidence that it
1510b57cec5SDimitry Andric   /// will be properly predicted.
1520b57cec5SDimitry Andric   bool isProfitableToIfCvt(MachineBasicBlock &TMBB,
1530b57cec5SDimitry Andric                            unsigned NumTCycles, unsigned ExtraTCycles,
1540b57cec5SDimitry Andric                            MachineBasicBlock &FMBB,
1550b57cec5SDimitry Andric                            unsigned NumFCycles, unsigned ExtraFCycles,
1560b57cec5SDimitry Andric                            BranchProbability Probability) const override;
1570b57cec5SDimitry Andric 
1580b57cec5SDimitry Andric   /// Return true if it's profitable for if-converter to duplicate instructions
1590b57cec5SDimitry Andric   /// of specified accumulated instruction latencies in the specified MBB to
1600b57cec5SDimitry Andric   /// enable if-conversion.
1610b57cec5SDimitry Andric   /// The probability of the instructions being executed is given by
1620b57cec5SDimitry Andric   /// Probability, and Confidence is a measure of our confidence that it
1630b57cec5SDimitry Andric   /// will be properly predicted.
1640b57cec5SDimitry Andric   bool isProfitableToDupForIfCvt(MachineBasicBlock &MBB, unsigned NumCycles,
1650b57cec5SDimitry Andric                                  BranchProbability Probability) const override;
1660b57cec5SDimitry Andric 
1670b57cec5SDimitry Andric   /// Emit instructions to copy a pair of physical registers.
1680b57cec5SDimitry Andric   ///
1690b57cec5SDimitry Andric   /// This function should support copies within any legal register class as
1700b57cec5SDimitry Andric   /// well as any cross-class copies created during instruction selection.
1710b57cec5SDimitry Andric   ///
1720b57cec5SDimitry Andric   /// The source and destination registers may overlap, which may require a
1730b57cec5SDimitry Andric   /// careful implementation when multiple copy instructions are required for
1740b57cec5SDimitry Andric   /// large registers. See for example the ARM target.
1750b57cec5SDimitry Andric   void copyPhysReg(MachineBasicBlock &MBB, MachineBasicBlock::iterator I,
176480093f4SDimitry Andric                    const DebugLoc &DL, MCRegister DestReg, MCRegister SrcReg,
1770b57cec5SDimitry Andric                    bool KillSrc) const override;
1780b57cec5SDimitry Andric 
1790b57cec5SDimitry Andric   /// Store the specified register of the given register class to the specified
1800b57cec5SDimitry Andric   /// stack frame index. The store instruction is to be added to the given
1810b57cec5SDimitry Andric   /// machine basic block before the specified machine instruction. If isKill
1820b57cec5SDimitry Andric   /// is true, the register operand is the last use and must be marked kill.
1830b57cec5SDimitry Andric   void storeRegToStackSlot(MachineBasicBlock &MBB,
184bdd1243dSDimitry Andric                            MachineBasicBlock::iterator MBBI, Register SrcReg,
185bdd1243dSDimitry Andric                            bool isKill, int FrameIndex,
1860b57cec5SDimitry Andric                            const TargetRegisterClass *RC,
187bdd1243dSDimitry Andric                            const TargetRegisterInfo *TRI,
188bdd1243dSDimitry Andric                            Register VReg) const override;
1890b57cec5SDimitry Andric 
1900b57cec5SDimitry Andric   /// Load the specified register of the given register class from the specified
1910b57cec5SDimitry Andric   /// stack frame index. The load instruction is to be added to the given
1920b57cec5SDimitry Andric   /// machine basic block before the specified machine instruction.
1930b57cec5SDimitry Andric   void loadRegFromStackSlot(MachineBasicBlock &MBB,
194bdd1243dSDimitry Andric                             MachineBasicBlock::iterator MBBI, Register DestReg,
195bdd1243dSDimitry Andric                             int FrameIndex, const TargetRegisterClass *RC,
196bdd1243dSDimitry Andric                             const TargetRegisterInfo *TRI,
197bdd1243dSDimitry Andric                             Register VReg) const override;
1980b57cec5SDimitry Andric 
1990b57cec5SDimitry Andric   /// This function is called for all pseudo instructions
2000b57cec5SDimitry Andric   /// that remain after register allocation. Many pseudo instructions are
2010b57cec5SDimitry Andric   /// created to help register allocation. This is the place to convert them
2020b57cec5SDimitry Andric   /// into real instructions. The target can edit MI in place, or it can insert
2030b57cec5SDimitry Andric   /// new instructions and erase MI. The function should return true if
2040b57cec5SDimitry Andric   /// anything was changed.
2050b57cec5SDimitry Andric   bool expandPostRAPseudo(MachineInstr &MI) const override;
2060b57cec5SDimitry Andric 
2070b57cec5SDimitry Andric   /// Get the base register and byte offset of a load/store instr.
2085ffd83dbSDimitry Andric   bool getMemOperandsWithOffsetWidth(
2095ffd83dbSDimitry Andric       const MachineInstr &LdSt,
2105ffd83dbSDimitry Andric       SmallVectorImpl<const MachineOperand *> &BaseOps, int64_t &Offset,
211*0fca6ea1SDimitry Andric       bool &OffsetIsScalable, LocationSize &Width,
2120b57cec5SDimitry Andric       const TargetRegisterInfo *TRI) const override;
2130b57cec5SDimitry Andric 
2140b57cec5SDimitry Andric   /// Reverses the branch condition of the specified condition list,
2150b57cec5SDimitry Andric   /// returning false on success and true if it cannot be reversed.
2160b57cec5SDimitry Andric   bool reverseBranchCondition(SmallVectorImpl<MachineOperand> &Cond)
2170b57cec5SDimitry Andric         const override;
2180b57cec5SDimitry Andric 
2190b57cec5SDimitry Andric   /// Insert a noop into the instruction stream at the specified point.
2200b57cec5SDimitry Andric   void insertNoop(MachineBasicBlock &MBB,
2210b57cec5SDimitry Andric                   MachineBasicBlock::iterator MI) const override;
2220b57cec5SDimitry Andric 
2230b57cec5SDimitry Andric   /// Returns true if the instruction is already predicated.
2240b57cec5SDimitry Andric   bool isPredicated(const MachineInstr &MI) const override;
2250b57cec5SDimitry Andric 
2260b57cec5SDimitry Andric   /// Return true for post-incremented instructions.
2270b57cec5SDimitry Andric   bool isPostIncrement(const MachineInstr &MI) const override;
2280b57cec5SDimitry Andric 
2290b57cec5SDimitry Andric   /// Convert the instruction into a predicated instruction.
2300b57cec5SDimitry Andric   /// It returns true if the operation was successful.
2310b57cec5SDimitry Andric   bool PredicateInstruction(MachineInstr &MI,
2320b57cec5SDimitry Andric                             ArrayRef<MachineOperand> Cond) const override;
2330b57cec5SDimitry Andric 
2340b57cec5SDimitry Andric   /// Returns true if the first specified predicate
2350b57cec5SDimitry Andric   /// subsumes the second, e.g. GE subsumes GT.
2360b57cec5SDimitry Andric   bool SubsumesPredicate(ArrayRef<MachineOperand> Pred1,
2370b57cec5SDimitry Andric                          ArrayRef<MachineOperand> Pred2) const override;
2380b57cec5SDimitry Andric 
2390b57cec5SDimitry Andric   /// If the specified instruction defines any predicate
2400b57cec5SDimitry Andric   /// or condition code register(s) used for predication, returns true as well
2410b57cec5SDimitry Andric   /// as the definition predicate(s) by reference.
242e8d8bef9SDimitry Andric   bool ClobbersPredicate(MachineInstr &MI, std::vector<MachineOperand> &Pred,
243e8d8bef9SDimitry Andric                          bool SkipDead) const override;
2440b57cec5SDimitry Andric 
2450b57cec5SDimitry Andric   /// Return true if the specified instruction can be predicated.
2460b57cec5SDimitry Andric   /// By default, this returns true for every instruction with a
2470b57cec5SDimitry Andric   /// PredicateOperand.
2480b57cec5SDimitry Andric   bool isPredicable(const MachineInstr &MI) const override;
2490b57cec5SDimitry Andric 
2500b57cec5SDimitry Andric   /// Test if the given instruction should be considered a scheduling boundary.
2510b57cec5SDimitry Andric   /// This primarily includes labels and terminators.
2520b57cec5SDimitry Andric   bool isSchedulingBoundary(const MachineInstr &MI,
2530b57cec5SDimitry Andric                             const MachineBasicBlock *MBB,
2540b57cec5SDimitry Andric                             const MachineFunction &MF) const override;
2550b57cec5SDimitry Andric 
2560b57cec5SDimitry Andric   /// Measure the specified inline asm to determine an approximation of its
2570b57cec5SDimitry Andric   /// length.
2580b57cec5SDimitry Andric   unsigned getInlineAsmLength(
2590b57cec5SDimitry Andric     const char *Str,
2600b57cec5SDimitry Andric     const MCAsmInfo &MAI,
2610b57cec5SDimitry Andric     const TargetSubtargetInfo *STI = nullptr) const override;
2620b57cec5SDimitry Andric 
2630b57cec5SDimitry Andric   /// Allocate and return a hazard recognizer to use for this target when
2640b57cec5SDimitry Andric   /// scheduling the machine instructions after register allocation.
2650b57cec5SDimitry Andric   ScheduleHazardRecognizer*
2660b57cec5SDimitry Andric   CreateTargetPostRAHazardRecognizer(const InstrItineraryData *II,
2670b57cec5SDimitry Andric                                      const ScheduleDAG *DAG) const override;
2680b57cec5SDimitry Andric 
2690b57cec5SDimitry Andric   /// For a comparison instruction, return the source registers
2700b57cec5SDimitry Andric   /// in SrcReg and SrcReg2 if having two register operands, and the value it
2710b57cec5SDimitry Andric   /// compares against in CmpValue. Return true if the comparison instruction
2720b57cec5SDimitry Andric   /// can be analyzed.
2735ffd83dbSDimitry Andric   bool analyzeCompare(const MachineInstr &MI, Register &SrcReg,
274349cc55cSDimitry Andric                       Register &SrcReg2, int64_t &Mask,
275349cc55cSDimitry Andric                       int64_t &Value) const override;
2760b57cec5SDimitry Andric 
2770b57cec5SDimitry Andric   /// Compute the instruction latency of a given instruction.
2780b57cec5SDimitry Andric   /// If the instruction has higher cost when predicated, it's returned via
2790b57cec5SDimitry Andric   /// PredCost.
2800b57cec5SDimitry Andric   unsigned getInstrLatency(const InstrItineraryData *ItinData,
2810b57cec5SDimitry Andric                            const MachineInstr &MI,
2820b57cec5SDimitry Andric                            unsigned *PredCost = nullptr) const override;
2830b57cec5SDimitry Andric 
2840b57cec5SDimitry Andric   /// Create machine specific model for scheduling.
2850b57cec5SDimitry Andric   DFAPacketizer *
2860b57cec5SDimitry Andric   CreateTargetScheduleState(const TargetSubtargetInfo &STI) const override;
2870b57cec5SDimitry Andric 
2880b57cec5SDimitry Andric   // Sometimes, it is possible for the target
2890b57cec5SDimitry Andric   // to tell, even without aliasing information, that two MIs access different
2900b57cec5SDimitry Andric   // memory addresses. This function returns true if two MIs access different
2910b57cec5SDimitry Andric   // memory addresses and false otherwise.
2920b57cec5SDimitry Andric   bool
2930b57cec5SDimitry Andric   areMemAccessesTriviallyDisjoint(const MachineInstr &MIa,
2948bcb0991SDimitry Andric                                   const MachineInstr &MIb) const override;
2950b57cec5SDimitry Andric 
2960b57cec5SDimitry Andric   /// For instructions with a base and offset, return the position of the
2970b57cec5SDimitry Andric   /// base register and offset operands.
2980b57cec5SDimitry Andric   bool getBaseAndOffsetPosition(const MachineInstr &MI, unsigned &BasePos,
2990b57cec5SDimitry Andric                                 unsigned &OffsetPos) const override;
3000b57cec5SDimitry Andric 
3010b57cec5SDimitry Andric   /// If the instruction is an increment of a constant value, return the amount.
3020b57cec5SDimitry Andric   bool getIncrementValue(const MachineInstr &MI, int &Value) const override;
3030b57cec5SDimitry Andric 
3040b57cec5SDimitry Andric   /// getOperandLatency - Compute and return the use operand latency of a given
3050b57cec5SDimitry Andric   /// pair of def and use.
3060b57cec5SDimitry Andric   /// In most cases, the static scheduling itinerary was enough to determine the
3070b57cec5SDimitry Andric   /// operand latency. But it may not be possible for instructions with variable
3080b57cec5SDimitry Andric   /// number of defs / uses.
3090b57cec5SDimitry Andric   ///
3100b57cec5SDimitry Andric   /// This is a raw interface to the itinerary that may be directly overriden by
3110b57cec5SDimitry Andric   /// a target. Use computeOperandLatency to get the best estimate of latency.
3125f757f3fSDimitry Andric   std::optional<unsigned> getOperandLatency(const InstrItineraryData *ItinData,
3135f757f3fSDimitry Andric                                             const MachineInstr &DefMI,
3145f757f3fSDimitry Andric                                             unsigned DefIdx,
3150b57cec5SDimitry Andric                                             const MachineInstr &UseMI,
3160b57cec5SDimitry Andric                                             unsigned UseIdx) const override;
3170b57cec5SDimitry Andric 
3180b57cec5SDimitry Andric   /// Decompose the machine operand's target flags into two values - the direct
3190b57cec5SDimitry Andric   /// target flag value and any of bit flags that are applied.
3200b57cec5SDimitry Andric   std::pair<unsigned, unsigned>
3210b57cec5SDimitry Andric   decomposeMachineOperandsTargetFlags(unsigned TF) const override;
3220b57cec5SDimitry Andric 
3230b57cec5SDimitry Andric   /// Return an array that contains the direct target flag values and their
3240b57cec5SDimitry Andric   /// names.
3250b57cec5SDimitry Andric   ///
3260b57cec5SDimitry Andric   /// MIR Serialization is able to serialize only the target flags that are
3270b57cec5SDimitry Andric   /// defined by this method.
3280b57cec5SDimitry Andric   ArrayRef<std::pair<unsigned, const char *>>
3290b57cec5SDimitry Andric   getSerializableDirectMachineOperandTargetFlags() const override;
3300b57cec5SDimitry Andric 
3310b57cec5SDimitry Andric   /// Return an array that contains the bitmask target flag values and their
3320b57cec5SDimitry Andric   /// names.
3330b57cec5SDimitry Andric   ///
3340b57cec5SDimitry Andric   /// MIR Serialization is able to serialize only the target flags that are
3350b57cec5SDimitry Andric   /// defined by this method.
3360b57cec5SDimitry Andric   ArrayRef<std::pair<unsigned, const char *>>
3370b57cec5SDimitry Andric   getSerializableBitmaskMachineOperandTargetFlags() const override;
3380b57cec5SDimitry Andric 
3390b57cec5SDimitry Andric   bool isTailCall(const MachineInstr &MI) const override;
34004eeddc0SDimitry Andric   bool isAsCheapAsAMove(const MachineInstr &MI) const override;
34104eeddc0SDimitry Andric 
34204eeddc0SDimitry Andric   // Return true if the instruction should be sunk by MachineSink.
34304eeddc0SDimitry Andric   // MachineSink determines on its own whether the instruction is safe to sink;
34404eeddc0SDimitry Andric   // this gives the target a hook to override the default behavior with regards
34504eeddc0SDimitry Andric   // to which instructions should be sunk.
34604eeddc0SDimitry Andric   bool shouldSink(const MachineInstr &MI) const override;
3470b57cec5SDimitry Andric 
3480b57cec5SDimitry Andric   /// HexagonInstrInfo specifics.
3490b57cec5SDimitry Andric 
350bdd1243dSDimitry Andric   Register createVR(MachineFunction *MF, MVT VT) const;
3510b57cec5SDimitry Andric   MachineInstr *findLoopInstr(MachineBasicBlock *BB, unsigned EndLoopOp,
3520b57cec5SDimitry Andric                               MachineBasicBlock *TargetBB,
3530b57cec5SDimitry Andric                               SmallPtrSet<MachineBasicBlock *, 8> &Visited) const;
3540b57cec5SDimitry Andric 
3550b57cec5SDimitry Andric   bool isAbsoluteSet(const MachineInstr &MI) const;
3560b57cec5SDimitry Andric   bool isAccumulator(const MachineInstr &MI) const;
3570b57cec5SDimitry Andric   bool isAddrModeWithOffset(const MachineInstr &MI) const;
3585ffd83dbSDimitry Andric   bool isBaseImmOffset(const MachineInstr &MI) const;
3590b57cec5SDimitry Andric   bool isComplex(const MachineInstr &MI) const;
3600b57cec5SDimitry Andric   bool isCompoundBranchInstr(const MachineInstr &MI) const;
3610b57cec5SDimitry Andric   bool isConstExtended(const MachineInstr &MI) const;
3620b57cec5SDimitry Andric   bool isDeallocRet(const MachineInstr &MI) const;
3630b57cec5SDimitry Andric   bool isDependent(const MachineInstr &ProdMI,
3640b57cec5SDimitry Andric                    const MachineInstr &ConsMI) const;
3650b57cec5SDimitry Andric   bool isDotCurInst(const MachineInstr &MI) const;
3660b57cec5SDimitry Andric   bool isDotNewInst(const MachineInstr &MI) const;
3670b57cec5SDimitry Andric   bool isDuplexPair(const MachineInstr &MIa, const MachineInstr &MIb) const;
3680b57cec5SDimitry Andric   bool isEndLoopN(unsigned Opcode) const;
3690b57cec5SDimitry Andric   bool isExpr(unsigned OpType) const;
3700b57cec5SDimitry Andric   bool isExtendable(const MachineInstr &MI) const;
3710b57cec5SDimitry Andric   bool isExtended(const MachineInstr &MI) const;
3720b57cec5SDimitry Andric   bool isFloat(const MachineInstr &MI) const;
3730b57cec5SDimitry Andric   bool isHVXMemWithAIndirect(const MachineInstr &I,
3740b57cec5SDimitry Andric                              const MachineInstr &J) const;
3750b57cec5SDimitry Andric   bool isIndirectCall(const MachineInstr &MI) const;
3760b57cec5SDimitry Andric   bool isIndirectL4Return(const MachineInstr &MI) const;
3770b57cec5SDimitry Andric   bool isJumpR(const MachineInstr &MI) const;
3780b57cec5SDimitry Andric   bool isJumpWithinBranchRange(const MachineInstr &MI, unsigned offset) const;
3790b57cec5SDimitry Andric   bool isLateSourceInstr(const MachineInstr &MI) const;
3800b57cec5SDimitry Andric   bool isLoopN(const MachineInstr &MI) const;
3810b57cec5SDimitry Andric   bool isMemOp(const MachineInstr &MI) const;
3820b57cec5SDimitry Andric   bool isNewValue(const MachineInstr &MI) const;
3830b57cec5SDimitry Andric   bool isNewValue(unsigned Opcode) const;
3840b57cec5SDimitry Andric   bool isNewValueInst(const MachineInstr &MI) const;
3850b57cec5SDimitry Andric   bool isNewValueJump(const MachineInstr &MI) const;
3860b57cec5SDimitry Andric   bool isNewValueJump(unsigned Opcode) const;
3870b57cec5SDimitry Andric   bool isNewValueStore(const MachineInstr &MI) const;
3880b57cec5SDimitry Andric   bool isNewValueStore(unsigned Opcode) const;
3890b57cec5SDimitry Andric   bool isOperandExtended(const MachineInstr &MI, unsigned OperandNum) const;
3900b57cec5SDimitry Andric   bool isPredicatedNew(const MachineInstr &MI) const;
3910b57cec5SDimitry Andric   bool isPredicatedNew(unsigned Opcode) const;
3920b57cec5SDimitry Andric   bool isPredicatedTrue(const MachineInstr &MI) const;
3930b57cec5SDimitry Andric   bool isPredicatedTrue(unsigned Opcode) const;
3940b57cec5SDimitry Andric   bool isPredicated(unsigned Opcode) const;
3950b57cec5SDimitry Andric   bool isPredicateLate(unsigned Opcode) const;
3960b57cec5SDimitry Andric   bool isPredictedTaken(unsigned Opcode) const;
3975ffd83dbSDimitry Andric   bool isPureSlot0(const MachineInstr &MI) const;
3985ffd83dbSDimitry Andric   bool isRestrictNoSlot1Store(const MachineInstr &MI) const;
3990b57cec5SDimitry Andric   bool isSaveCalleeSavedRegsCall(const MachineInstr &MI) const;
4000b57cec5SDimitry Andric   bool isSignExtendingLoad(const MachineInstr &MI) const;
4010b57cec5SDimitry Andric   bool isSolo(const MachineInstr &MI) const;
4020b57cec5SDimitry Andric   bool isSpillPredRegOp(const MachineInstr &MI) const;
4030b57cec5SDimitry Andric   bool isTC1(const MachineInstr &MI) const;
4040b57cec5SDimitry Andric   bool isTC2(const MachineInstr &MI) const;
4050b57cec5SDimitry Andric   bool isTC2Early(const MachineInstr &MI) const;
4060b57cec5SDimitry Andric   bool isTC4x(const MachineInstr &MI) const;
4070b57cec5SDimitry Andric   bool isToBeScheduledASAP(const MachineInstr &MI1,
4080b57cec5SDimitry Andric                            const MachineInstr &MI2) const;
4090b57cec5SDimitry Andric   bool isHVXVec(const MachineInstr &MI) const;
4100b57cec5SDimitry Andric   bool isValidAutoIncImm(const EVT VT, const int Offset) const;
4110b57cec5SDimitry Andric   bool isValidOffset(unsigned Opcode, int Offset,
4120b57cec5SDimitry Andric                      const TargetRegisterInfo *TRI, bool Extend = true) const;
4130b57cec5SDimitry Andric   bool isVecAcc(const MachineInstr &MI) const;
4140b57cec5SDimitry Andric   bool isVecALU(const MachineInstr &MI) const;
4150b57cec5SDimitry Andric   bool isVecUsableNextPacket(const MachineInstr &ProdMI,
4160b57cec5SDimitry Andric                              const MachineInstr &ConsMI) const;
4170b57cec5SDimitry Andric   bool isZeroExtendingLoad(const MachineInstr &MI) const;
4180b57cec5SDimitry Andric 
4190b57cec5SDimitry Andric   bool addLatencyToSchedule(const MachineInstr &MI1,
4200b57cec5SDimitry Andric                             const MachineInstr &MI2) const;
4210b57cec5SDimitry Andric   bool canExecuteInBundle(const MachineInstr &First,
4220b57cec5SDimitry Andric                           const MachineInstr &Second) const;
4230b57cec5SDimitry Andric   bool doesNotReturn(const MachineInstr &CallMI) const;
4240b57cec5SDimitry Andric   bool hasEHLabel(const MachineBasicBlock *B) const;
4250b57cec5SDimitry Andric   bool hasNonExtEquivalent(const MachineInstr &MI) const;
4260b57cec5SDimitry Andric   bool hasPseudoInstrPair(const MachineInstr &MI) const;
4270b57cec5SDimitry Andric   bool hasUncondBranch(const MachineBasicBlock *B) const;
4280b57cec5SDimitry Andric   bool mayBeCurLoad(const MachineInstr &MI) const;
4290b57cec5SDimitry Andric   bool mayBeNewStore(const MachineInstr &MI) const;
4300b57cec5SDimitry Andric   bool producesStall(const MachineInstr &ProdMI,
4310b57cec5SDimitry Andric                      const MachineInstr &ConsMI) const;
4320b57cec5SDimitry Andric   bool producesStall(const MachineInstr &MI,
4330b57cec5SDimitry Andric                      MachineBasicBlock::const_instr_iterator MII) const;
434bdd1243dSDimitry Andric   bool predCanBeUsedAsDotNew(const MachineInstr &MI, Register PredReg) const;
4350b57cec5SDimitry Andric   bool PredOpcodeHasJMP_c(unsigned Opcode) const;
4360b57cec5SDimitry Andric   bool predOpcodeHasNot(ArrayRef<MachineOperand> Cond) const;
4370b57cec5SDimitry Andric 
4380b57cec5SDimitry Andric   unsigned getAddrMode(const MachineInstr &MI) const;
4390b57cec5SDimitry Andric   MachineOperand *getBaseAndOffset(const MachineInstr &MI, int64_t &Offset,
440*0fca6ea1SDimitry Andric                                    LocationSize &AccessSize) const;
4410b57cec5SDimitry Andric   SmallVector<MachineInstr*,2> getBranchingInstrs(MachineBasicBlock& MBB) const;
4420b57cec5SDimitry Andric   unsigned getCExtOpNum(const MachineInstr &MI) const;
4430b57cec5SDimitry Andric   HexagonII::CompoundGroup
4440b57cec5SDimitry Andric   getCompoundCandidateGroup(const MachineInstr &MI) const;
4450b57cec5SDimitry Andric   unsigned getCompoundOpcode(const MachineInstr &GA,
4460b57cec5SDimitry Andric                              const MachineInstr &GB) const;
4475ffd83dbSDimitry Andric   int getDuplexOpcode(const MachineInstr &MI, bool ForBigCore = true) const;
4480b57cec5SDimitry Andric   int getCondOpcode(int Opc, bool sense) const;
4490b57cec5SDimitry Andric   int getDotCurOp(const MachineInstr &MI) const;
4500b57cec5SDimitry Andric   int getNonDotCurOp(const MachineInstr &MI) const;
4510b57cec5SDimitry Andric   int getDotNewOp(const MachineInstr &MI) const;
4520b57cec5SDimitry Andric   int getDotNewPredJumpOp(const MachineInstr &MI,
4530b57cec5SDimitry Andric                           const MachineBranchProbabilityInfo *MBPI) const;
4540b57cec5SDimitry Andric   int getDotNewPredOp(const MachineInstr &MI,
4550b57cec5SDimitry Andric                       const MachineBranchProbabilityInfo *MBPI) const;
4560b57cec5SDimitry Andric   int getDotOldOp(const MachineInstr &MI) const;
4570b57cec5SDimitry Andric   HexagonII::SubInstructionGroup getDuplexCandidateGroup(const MachineInstr &MI)
4580b57cec5SDimitry Andric                                                          const;
4590b57cec5SDimitry Andric   short getEquivalentHWInstr(const MachineInstr &MI) const;
4600b57cec5SDimitry Andric   unsigned getInstrTimingClassLatency(const InstrItineraryData *ItinData,
4610b57cec5SDimitry Andric                                       const MachineInstr &MI) const;
4620b57cec5SDimitry Andric   bool getInvertedPredSense(SmallVectorImpl<MachineOperand> &Cond) const;
4630b57cec5SDimitry Andric   unsigned getInvertedPredicatedOpcode(const int Opc) const;
4640b57cec5SDimitry Andric   int getMaxValue(const MachineInstr &MI) const;
4650b57cec5SDimitry Andric   unsigned getMemAccessSize(const MachineInstr &MI) const;
4660b57cec5SDimitry Andric   int getMinValue(const MachineInstr &MI) const;
4670b57cec5SDimitry Andric   short getNonExtOpcode(const MachineInstr &MI) const;
468bdd1243dSDimitry Andric   bool getPredReg(ArrayRef<MachineOperand> Cond, Register &PredReg,
4690b57cec5SDimitry Andric                   unsigned &PredRegPos, unsigned &PredRegFlags) const;
4700b57cec5SDimitry Andric   short getPseudoInstrPair(const MachineInstr &MI) const;
4710b57cec5SDimitry Andric   short getRegForm(const MachineInstr &MI) const;
4720b57cec5SDimitry Andric   unsigned getSize(const MachineInstr &MI) const;
4730b57cec5SDimitry Andric   uint64_t getType(const MachineInstr &MI) const;
4745ffd83dbSDimitry Andric   InstrStage::FuncUnits getUnits(const MachineInstr &MI) const;
4750b57cec5SDimitry Andric 
4760b57cec5SDimitry Andric   MachineBasicBlock::instr_iterator expandVGatherPseudo(MachineInstr &MI) const;
4770b57cec5SDimitry Andric 
4780b57cec5SDimitry Andric   /// getInstrTimingClassLatency - Compute the instruction latency of a given
4790b57cec5SDimitry Andric   /// instruction using Timing Class information, if available.
4800b57cec5SDimitry Andric   unsigned nonDbgBBSize(const MachineBasicBlock *BB) const;
4810b57cec5SDimitry Andric   unsigned nonDbgBundleSize(MachineBasicBlock::const_iterator BundleHead) const;
4820b57cec5SDimitry Andric 
4830b57cec5SDimitry Andric   void immediateExtend(MachineInstr &MI) const;
4840b57cec5SDimitry Andric   bool invertAndChangeJumpTarget(MachineInstr &MI,
4850b57cec5SDimitry Andric                                  MachineBasicBlock *NewTarget) const;
4860b57cec5SDimitry Andric   void genAllInsnTimingClasses(MachineFunction &MF) const;
4870b57cec5SDimitry Andric   bool reversePredSense(MachineInstr &MI) const;
4880b57cec5SDimitry Andric   unsigned reversePrediction(unsigned Opcode) const;
4890b57cec5SDimitry Andric   bool validateBranchCond(const ArrayRef<MachineOperand> &Cond) const;
4900b57cec5SDimitry Andric 
4910b57cec5SDimitry Andric   void setBundleNoShuf(MachineBasicBlock::instr_iterator MIB) const;
4920b57cec5SDimitry Andric   bool getBundleNoShuf(const MachineInstr &MIB) const;
4935ffd83dbSDimitry Andric 
4945ffd83dbSDimitry Andric   // When TinyCore with Duplexes is enabled, this function is used to translate
4955ffd83dbSDimitry Andric   // tiny-instructions to big-instructions and vice versa to get the slot
4965ffd83dbSDimitry Andric   // consumption.
4975ffd83dbSDimitry Andric   void changeDuplexOpcode(MachineBasicBlock::instr_iterator MII,
4985ffd83dbSDimitry Andric                           bool ToBigInstrs) const;
4995ffd83dbSDimitry Andric   void translateInstrsForDup(MachineFunction &MF,
5005ffd83dbSDimitry Andric                              bool ToBigInstrs = true) const;
5015ffd83dbSDimitry Andric   void translateInstrsForDup(MachineBasicBlock::instr_iterator MII,
5025ffd83dbSDimitry Andric                              bool ToBigInstrs) const;
5035ffd83dbSDimitry Andric 
5040b57cec5SDimitry Andric   // Addressing mode relations.
5050b57cec5SDimitry Andric   short changeAddrMode_abs_io(short Opc) const;
5060b57cec5SDimitry Andric   short changeAddrMode_io_abs(short Opc) const;
5070b57cec5SDimitry Andric   short changeAddrMode_io_pi(short Opc) const;
5080b57cec5SDimitry Andric   short changeAddrMode_io_rr(short Opc) const;
5090b57cec5SDimitry Andric   short changeAddrMode_pi_io(short Opc) const;
5100b57cec5SDimitry Andric   short changeAddrMode_rr_io(short Opc) const;
5110b57cec5SDimitry Andric   short changeAddrMode_rr_ur(short Opc) const;
5120b57cec5SDimitry Andric   short changeAddrMode_ur_rr(short Opc) const;
5130b57cec5SDimitry Andric 
changeAddrMode_abs_io(const MachineInstr & MI)5140b57cec5SDimitry Andric   short changeAddrMode_abs_io(const MachineInstr &MI) const {
5150b57cec5SDimitry Andric     return changeAddrMode_abs_io(MI.getOpcode());
5160b57cec5SDimitry Andric   }
changeAddrMode_io_abs(const MachineInstr & MI)5170b57cec5SDimitry Andric   short changeAddrMode_io_abs(const MachineInstr &MI) const {
5180b57cec5SDimitry Andric     return changeAddrMode_io_abs(MI.getOpcode());
5190b57cec5SDimitry Andric   }
changeAddrMode_io_rr(const MachineInstr & MI)5200b57cec5SDimitry Andric   short changeAddrMode_io_rr(const MachineInstr &MI) const {
5210b57cec5SDimitry Andric     return changeAddrMode_io_rr(MI.getOpcode());
5220b57cec5SDimitry Andric   }
changeAddrMode_rr_io(const MachineInstr & MI)5230b57cec5SDimitry Andric   short changeAddrMode_rr_io(const MachineInstr &MI) const {
5240b57cec5SDimitry Andric     return changeAddrMode_rr_io(MI.getOpcode());
5250b57cec5SDimitry Andric   }
changeAddrMode_rr_ur(const MachineInstr & MI)5260b57cec5SDimitry Andric   short changeAddrMode_rr_ur(const MachineInstr &MI) const {
5270b57cec5SDimitry Andric     return changeAddrMode_rr_ur(MI.getOpcode());
5280b57cec5SDimitry Andric   }
changeAddrMode_ur_rr(const MachineInstr & MI)5290b57cec5SDimitry Andric   short changeAddrMode_ur_rr(const MachineInstr &MI) const {
5300b57cec5SDimitry Andric     return changeAddrMode_ur_rr(MI.getOpcode());
5310b57cec5SDimitry Andric   }
5320eae32dcSDimitry Andric 
5330eae32dcSDimitry Andric   MCInst getNop() const override;
5340b57cec5SDimitry Andric };
5350b57cec5SDimitry Andric 
5360b57cec5SDimitry Andric } // end namespace llvm
5370b57cec5SDimitry Andric 
5380b57cec5SDimitry Andric #endif // LLVM_LIB_TARGET_HEXAGON_HEXAGONINSTRINFO_H
539