xref: /freebsd/contrib/llvm-project/llvm/lib/Target/PowerPC/PPCInstrInfo.h (revision 0fca6ea1d4eea4c934cfff25ac9ee8ad6fe95583)
10b57cec5SDimitry Andric //===-- PPCInstrInfo.h - PowerPC 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 PowerPC implementation of the TargetInstrInfo class.
100b57cec5SDimitry Andric //
110b57cec5SDimitry Andric //===----------------------------------------------------------------------===//
120b57cec5SDimitry Andric 
130b57cec5SDimitry Andric #ifndef LLVM_LIB_TARGET_POWERPC_PPCINSTRINFO_H
140b57cec5SDimitry Andric #define LLVM_LIB_TARGET_POWERPC_PPCINSTRINFO_H
150b57cec5SDimitry Andric 
165f757f3fSDimitry Andric #include "MCTargetDesc/PPCMCTargetDesc.h"
175f757f3fSDimitry Andric #include "PPC.h"
180b57cec5SDimitry Andric #include "PPCRegisterInfo.h"
195f757f3fSDimitry Andric #include "llvm/ADT/SmallSet.h"
200b57cec5SDimitry Andric #include "llvm/CodeGen/TargetInstrInfo.h"
210b57cec5SDimitry Andric 
220b57cec5SDimitry Andric #define GET_INSTRINFO_HEADER
230b57cec5SDimitry Andric #include "PPCGenInstrInfo.inc"
240b57cec5SDimitry Andric 
250b57cec5SDimitry Andric namespace llvm {
260b57cec5SDimitry Andric 
270b57cec5SDimitry Andric // Instructions that have an immediate form might be convertible to that
280b57cec5SDimitry Andric // form if the correct input is a result of a load immediate. In order to
290b57cec5SDimitry Andric // know whether the transformation is special, we might need to know some
300b57cec5SDimitry Andric // of the details of the two forms.
310b57cec5SDimitry Andric struct ImmInstrInfo {
320b57cec5SDimitry Andric   // Is the immediate field in the immediate form signed or unsigned?
330b57cec5SDimitry Andric   uint64_t SignedImm : 1;
340b57cec5SDimitry Andric   // Does the immediate need to be a multiple of some value?
350b57cec5SDimitry Andric   uint64_t ImmMustBeMultipleOf : 5;
360b57cec5SDimitry Andric   // Is R0/X0 treated specially by the original r+r instruction?
370b57cec5SDimitry Andric   // If so, in which operand?
380b57cec5SDimitry Andric   uint64_t ZeroIsSpecialOrig : 3;
390b57cec5SDimitry Andric   // Is R0/X0 treated specially by the new r+i instruction?
400b57cec5SDimitry Andric   // If so, in which operand?
410b57cec5SDimitry Andric   uint64_t ZeroIsSpecialNew : 3;
420b57cec5SDimitry Andric   // Is the operation commutative?
430b57cec5SDimitry Andric   uint64_t IsCommutative : 1;
440b57cec5SDimitry Andric   // The operand number to check for add-immediate def.
450b57cec5SDimitry Andric   uint64_t OpNoForForwarding : 3;
460b57cec5SDimitry Andric   // The operand number for the immediate.
470b57cec5SDimitry Andric   uint64_t ImmOpNo : 3;
480b57cec5SDimitry Andric   // The opcode of the new instruction.
490b57cec5SDimitry Andric   uint64_t ImmOpcode : 16;
500b57cec5SDimitry Andric   // The size of the immediate.
510b57cec5SDimitry Andric   uint64_t ImmWidth : 5;
520b57cec5SDimitry Andric   // The immediate should be truncated to N bits.
530b57cec5SDimitry Andric   uint64_t TruncateImmTo : 5;
540b57cec5SDimitry Andric   // Is the instruction summing the operand
550b57cec5SDimitry Andric   uint64_t IsSummingOperands : 1;
560b57cec5SDimitry Andric };
570b57cec5SDimitry Andric 
580b57cec5SDimitry Andric // Information required to convert an instruction to just a materialized
590b57cec5SDimitry Andric // immediate.
600b57cec5SDimitry Andric struct LoadImmediateInfo {
610b57cec5SDimitry Andric   unsigned Imm : 16;
620b57cec5SDimitry Andric   unsigned Is64Bit : 1;
630b57cec5SDimitry Andric   unsigned SetCR : 1;
640b57cec5SDimitry Andric };
650b57cec5SDimitry Andric 
665ffd83dbSDimitry Andric // Index into the OpcodesForSpill array.
675ffd83dbSDimitry Andric enum SpillOpcodeKey {
685ffd83dbSDimitry Andric   SOK_Int4Spill,
695ffd83dbSDimitry Andric   SOK_Int8Spill,
705ffd83dbSDimitry Andric   SOK_Float8Spill,
715ffd83dbSDimitry Andric   SOK_Float4Spill,
725ffd83dbSDimitry Andric   SOK_CRSpill,
735ffd83dbSDimitry Andric   SOK_CRBitSpill,
745ffd83dbSDimitry Andric   SOK_VRVectorSpill,
755ffd83dbSDimitry Andric   SOK_VSXVectorSpill,
765ffd83dbSDimitry Andric   SOK_VectorFloat8Spill,
775ffd83dbSDimitry Andric   SOK_VectorFloat4Spill,
785ffd83dbSDimitry Andric   SOK_SpillToVSR,
79e8d8bef9SDimitry Andric   SOK_PairedVecSpill,
80e8d8bef9SDimitry Andric   SOK_AccumulatorSpill,
81e8d8bef9SDimitry Andric   SOK_UAccumulatorSpill,
82bdd1243dSDimitry Andric   SOK_WAccumulatorSpill,
835ffd83dbSDimitry Andric   SOK_SPESpill,
84fe6060f1SDimitry Andric   SOK_PairedG8Spill,
855ffd83dbSDimitry Andric   SOK_LastOpcodeSpill // This must be last on the enum.
865ffd83dbSDimitry Andric };
875ffd83dbSDimitry Andric 
88*0fca6ea1SDimitry Andric // PPC MachineCombiner patterns
89*0fca6ea1SDimitry Andric enum PPCMachineCombinerPattern : unsigned {
90*0fca6ea1SDimitry Andric   // These are patterns matched by the PowerPC to reassociate FMA chains.
91*0fca6ea1SDimitry Andric   REASSOC_XY_AMM_BMM = MachineCombinerPattern::TARGET_PATTERN_START,
92*0fca6ea1SDimitry Andric   REASSOC_XMM_AMM_BMM,
93*0fca6ea1SDimitry Andric 
94*0fca6ea1SDimitry Andric   // These are patterns matched by the PowerPC to reassociate FMA and FSUB to
95*0fca6ea1SDimitry Andric   // reduce register pressure.
96*0fca6ea1SDimitry Andric   REASSOC_XY_BCA,
97*0fca6ea1SDimitry Andric   REASSOC_XY_BAC,
98*0fca6ea1SDimitry Andric 
99*0fca6ea1SDimitry Andric };
100*0fca6ea1SDimitry Andric 
1015ffd83dbSDimitry Andric // Define list of load and store spill opcodes.
102e8d8bef9SDimitry Andric #define NoInstr PPC::INSTRUCTION_LIST_END
1035ffd83dbSDimitry Andric #define Pwr8LoadOpcodes                                                        \
1045ffd83dbSDimitry Andric   {                                                                            \
1055ffd83dbSDimitry Andric     PPC::LWZ, PPC::LD, PPC::LFD, PPC::LFS, PPC::RESTORE_CR,                    \
1065ffd83dbSDimitry Andric         PPC::RESTORE_CRBIT, PPC::LVX, PPC::LXVD2X, PPC::LXSDX, PPC::LXSSPX,    \
107bdd1243dSDimitry Andric         PPC::SPILLTOVSR_LD, NoInstr, NoInstr, NoInstr, NoInstr, PPC::EVLDD,    \
108fe6060f1SDimitry Andric         PPC::RESTORE_QUADWORD                                                  \
1095ffd83dbSDimitry Andric   }
1105ffd83dbSDimitry Andric 
1115ffd83dbSDimitry Andric #define Pwr9LoadOpcodes                                                        \
1125ffd83dbSDimitry Andric   {                                                                            \
1135ffd83dbSDimitry Andric     PPC::LWZ, PPC::LD, PPC::LFD, PPC::LFS, PPC::RESTORE_CR,                    \
1145ffd83dbSDimitry Andric         PPC::RESTORE_CRBIT, PPC::LVX, PPC::LXV, PPC::DFLOADf64,                \
115fe6060f1SDimitry Andric         PPC::DFLOADf32, PPC::SPILLTOVSR_LD, NoInstr, NoInstr, NoInstr,         \
116bdd1243dSDimitry Andric         NoInstr, NoInstr, PPC::RESTORE_QUADWORD                                \
117e8d8bef9SDimitry Andric   }
118e8d8bef9SDimitry Andric 
119e8d8bef9SDimitry Andric #define Pwr10LoadOpcodes                                                       \
120e8d8bef9SDimitry Andric   {                                                                            \
121e8d8bef9SDimitry Andric     PPC::LWZ, PPC::LD, PPC::LFD, PPC::LFS, PPC::RESTORE_CR,                    \
122e8d8bef9SDimitry Andric         PPC::RESTORE_CRBIT, PPC::LVX, PPC::LXV, PPC::DFLOADf64,                \
123e8d8bef9SDimitry Andric         PPC::DFLOADf32, PPC::SPILLTOVSR_LD, PPC::LXVP, PPC::RESTORE_ACC,       \
124bdd1243dSDimitry Andric         PPC::RESTORE_UACC, NoInstr, NoInstr, PPC::RESTORE_QUADWORD             \
125bdd1243dSDimitry Andric   }
126bdd1243dSDimitry Andric 
127bdd1243dSDimitry Andric #define FutureLoadOpcodes                                                      \
128bdd1243dSDimitry Andric   {                                                                            \
129bdd1243dSDimitry Andric     PPC::LWZ, PPC::LD, PPC::LFD, PPC::LFS, PPC::RESTORE_CR,                    \
130bdd1243dSDimitry Andric         PPC::RESTORE_CRBIT, PPC::LVX, PPC::LXV, PPC::DFLOADf64,                \
131bdd1243dSDimitry Andric         PPC::DFLOADf32, PPC::SPILLTOVSR_LD, PPC::LXVP, PPC::RESTORE_ACC,       \
132bdd1243dSDimitry Andric         PPC::RESTORE_UACC, PPC::RESTORE_WACC, NoInstr, PPC::RESTORE_QUADWORD   \
1335ffd83dbSDimitry Andric   }
1345ffd83dbSDimitry Andric 
1355ffd83dbSDimitry Andric #define Pwr8StoreOpcodes                                                       \
1365ffd83dbSDimitry Andric   {                                                                            \
1375ffd83dbSDimitry Andric     PPC::STW, PPC::STD, PPC::STFD, PPC::STFS, PPC::SPILL_CR, PPC::SPILL_CRBIT, \
138e8d8bef9SDimitry Andric         PPC::STVX, PPC::STXVD2X, PPC::STXSDX, PPC::STXSSPX,                    \
139bdd1243dSDimitry Andric         PPC::SPILLTOVSR_ST, NoInstr, NoInstr, NoInstr, NoInstr, PPC::EVSTDD,   \
140fe6060f1SDimitry Andric         PPC::SPILL_QUADWORD                                                    \
1415ffd83dbSDimitry Andric   }
1425ffd83dbSDimitry Andric 
1435ffd83dbSDimitry Andric #define Pwr9StoreOpcodes                                                       \
1445ffd83dbSDimitry Andric   {                                                                            \
1455ffd83dbSDimitry Andric     PPC::STW, PPC::STD, PPC::STFD, PPC::STFS, PPC::SPILL_CR, PPC::SPILL_CRBIT, \
1465ffd83dbSDimitry Andric         PPC::STVX, PPC::STXV, PPC::DFSTOREf64, PPC::DFSTOREf32,                \
147bdd1243dSDimitry Andric         PPC::SPILLTOVSR_ST, NoInstr, NoInstr, NoInstr, NoInstr, NoInstr,       \
148fe6060f1SDimitry Andric         PPC::SPILL_QUADWORD                                                    \
149e8d8bef9SDimitry Andric   }
150e8d8bef9SDimitry Andric 
151e8d8bef9SDimitry Andric #define Pwr10StoreOpcodes                                                      \
152e8d8bef9SDimitry Andric   {                                                                            \
153e8d8bef9SDimitry Andric     PPC::STW, PPC::STD, PPC::STFD, PPC::STFS, PPC::SPILL_CR, PPC::SPILL_CRBIT, \
154e8d8bef9SDimitry Andric         PPC::STVX, PPC::STXV, PPC::DFSTOREf64, PPC::DFSTOREf32,                \
155e8d8bef9SDimitry Andric         PPC::SPILLTOVSR_ST, PPC::STXVP, PPC::SPILL_ACC, PPC::SPILL_UACC,       \
156bdd1243dSDimitry Andric         NoInstr, NoInstr, PPC::SPILL_QUADWORD                                  \
157bdd1243dSDimitry Andric   }
158bdd1243dSDimitry Andric 
159bdd1243dSDimitry Andric #define FutureStoreOpcodes                                                     \
160bdd1243dSDimitry Andric   {                                                                            \
161bdd1243dSDimitry Andric     PPC::STW, PPC::STD, PPC::STFD, PPC::STFS, PPC::SPILL_CR, PPC::SPILL_CRBIT, \
162bdd1243dSDimitry Andric         PPC::STVX, PPC::STXV, PPC::DFSTOREf64, PPC::DFSTOREf32,                \
163bdd1243dSDimitry Andric         PPC::SPILLTOVSR_ST, PPC::STXVP, PPC::SPILL_ACC, PPC::SPILL_UACC,       \
164bdd1243dSDimitry Andric         PPC::SPILL_WACC, NoInstr, PPC::SPILL_QUADWORD                          \
1655ffd83dbSDimitry Andric   }
1665ffd83dbSDimitry Andric 
1675ffd83dbSDimitry Andric // Initialize arrays for load and store spill opcodes on supported subtargets.
1685ffd83dbSDimitry Andric #define StoreOpcodesForSpill                                                   \
169bdd1243dSDimitry Andric   { Pwr8StoreOpcodes, Pwr9StoreOpcodes, Pwr10StoreOpcodes, FutureStoreOpcodes }
1705ffd83dbSDimitry Andric #define LoadOpcodesForSpill                                                    \
171bdd1243dSDimitry Andric   { Pwr8LoadOpcodes, Pwr9LoadOpcodes, Pwr10LoadOpcodes, FutureLoadOpcodes }
1725ffd83dbSDimitry Andric 
1730b57cec5SDimitry Andric class PPCSubtarget;
1740b57cec5SDimitry Andric class PPCInstrInfo : public PPCGenInstrInfo {
1750b57cec5SDimitry Andric   PPCSubtarget &Subtarget;
1760b57cec5SDimitry Andric   const PPCRegisterInfo RI;
177bdd1243dSDimitry Andric   const unsigned StoreSpillOpcodesArray[4][SOK_LastOpcodeSpill] =
1785ffd83dbSDimitry Andric       StoreOpcodesForSpill;
179bdd1243dSDimitry Andric   const unsigned LoadSpillOpcodesArray[4][SOK_LastOpcodeSpill] =
1805ffd83dbSDimitry Andric       LoadOpcodesForSpill;
1810b57cec5SDimitry Andric 
1820b57cec5SDimitry Andric   void StoreRegToStackSlot(MachineFunction &MF, unsigned SrcReg, bool isKill,
1830b57cec5SDimitry Andric                            int FrameIdx, const TargetRegisterClass *RC,
1840b57cec5SDimitry Andric                            SmallVectorImpl<MachineInstr *> &NewMIs) const;
1850b57cec5SDimitry Andric   void LoadRegFromStackSlot(MachineFunction &MF, const DebugLoc &DL,
1860b57cec5SDimitry Andric                             unsigned DestReg, int FrameIdx,
1870b57cec5SDimitry Andric                             const TargetRegisterClass *RC,
1880b57cec5SDimitry Andric                             SmallVectorImpl<MachineInstr *> &NewMIs) const;
1890b57cec5SDimitry Andric 
1905ffd83dbSDimitry Andric   // Replace the instruction with single LI if possible. \p DefMI must be LI or
1915ffd83dbSDimitry Andric   // LI8.
1925ffd83dbSDimitry Andric   bool simplifyToLI(MachineInstr &MI, MachineInstr &DefMI,
1935ffd83dbSDimitry Andric                     unsigned OpNoForForwarding, MachineInstr **KilledDef) const;
1945ffd83dbSDimitry Andric   // If the inst is imm-form and its register operand is produced by a ADDI, put
1955ffd83dbSDimitry Andric   // the imm into the inst directly and remove the ADDI if possible.
1965ffd83dbSDimitry Andric   bool transformToNewImmFormFedByAdd(MachineInstr &MI, MachineInstr &DefMI,
1975ffd83dbSDimitry Andric                                      unsigned OpNoForForwarding) const;
1985ffd83dbSDimitry Andric   // If the inst is x-form and has imm-form and one of its operand is produced
1995ffd83dbSDimitry Andric   // by a LI, put the imm into the inst directly and remove the LI if possible.
2000b57cec5SDimitry Andric   bool transformToImmFormFedByLI(MachineInstr &MI, const ImmInstrInfo &III,
2015ffd83dbSDimitry Andric                                  unsigned ConstantOpNo,
2025ffd83dbSDimitry Andric                                  MachineInstr &DefMI) const;
2035ffd83dbSDimitry Andric   // If the inst is x-form and has imm-form and one of its operand is produced
2045ffd83dbSDimitry Andric   // by an add-immediate, try to transform it when possible.
2050b57cec5SDimitry Andric   bool transformToImmFormFedByAdd(MachineInstr &MI, const ImmInstrInfo &III,
2060b57cec5SDimitry Andric                                   unsigned ConstantOpNo, MachineInstr &DefMI,
2070b57cec5SDimitry Andric                                   bool KillDefMI) const;
2080b57cec5SDimitry Andric   // Try to find that, if the instruction 'MI' contains any operand that
2090b57cec5SDimitry Andric   // could be forwarded from some inst that feeds it. If yes, return the
2100b57cec5SDimitry Andric   // Def of that operand. And OpNoForForwarding is the operand index in
2110b57cec5SDimitry Andric   // the 'MI' for that 'Def'. If we see another use of this Def between
2120b57cec5SDimitry Andric   // the Def and the MI, SeenIntermediateUse becomes 'true'.
2130b57cec5SDimitry Andric   MachineInstr *getForwardingDefMI(MachineInstr &MI,
2140b57cec5SDimitry Andric                                    unsigned &OpNoForForwarding,
2150b57cec5SDimitry Andric                                    bool &SeenIntermediateUse) const;
2160b57cec5SDimitry Andric 
2170b57cec5SDimitry Andric   // Can the user MI have it's source at index \p OpNoForForwarding
2180b57cec5SDimitry Andric   // forwarded from an add-immediate that feeds it?
2190b57cec5SDimitry Andric   bool isUseMIElgibleForForwarding(MachineInstr &MI, const ImmInstrInfo &III,
2200b57cec5SDimitry Andric                                    unsigned OpNoForForwarding) const;
2210b57cec5SDimitry Andric   bool isDefMIElgibleForForwarding(MachineInstr &DefMI,
2220b57cec5SDimitry Andric                                    const ImmInstrInfo &III,
2230b57cec5SDimitry Andric                                    MachineOperand *&ImmMO,
2240b57cec5SDimitry Andric                                    MachineOperand *&RegMO) const;
2250b57cec5SDimitry Andric   bool isImmElgibleForForwarding(const MachineOperand &ImmMO,
2260b57cec5SDimitry Andric                                  const MachineInstr &DefMI,
2270b57cec5SDimitry Andric                                  const ImmInstrInfo &III,
2285ffd83dbSDimitry Andric                                  int64_t &Imm,
2295ffd83dbSDimitry Andric                                  int64_t BaseImm = 0) const;
2300b57cec5SDimitry Andric   bool isRegElgibleForForwarding(const MachineOperand &RegMO,
2310b57cec5SDimitry Andric                                  const MachineInstr &DefMI,
2320b57cec5SDimitry Andric                                  const MachineInstr &MI, bool KillDefMI,
233bdd1243dSDimitry Andric                                  bool &IsFwdFeederRegKilled,
234bdd1243dSDimitry Andric                                  bool &SeenIntermediateUse) const;
2355ffd83dbSDimitry Andric   unsigned getSpillTarget() const;
236bdd1243dSDimitry Andric   ArrayRef<unsigned> getStoreOpcodesForSpillArray() const;
237bdd1243dSDimitry Andric   ArrayRef<unsigned> getLoadOpcodesForSpillArray() const;
238e8d8bef9SDimitry Andric   unsigned getSpillIndex(const TargetRegisterClass *RC) const;
2395ffd83dbSDimitry Andric   int16_t getFMAOpIdxInfo(unsigned Opcode) const;
240*0fca6ea1SDimitry Andric   void reassociateFMA(MachineInstr &Root, unsigned Pattern,
2415ffd83dbSDimitry Andric                       SmallVectorImpl<MachineInstr *> &InsInstrs,
2425ffd83dbSDimitry Andric                       SmallVectorImpl<MachineInstr *> &DelInstrs,
2435ffd83dbSDimitry Andric                       DenseMap<unsigned, unsigned> &InstrIdxForVirtReg) const;
244e8d8bef9SDimitry Andric   Register
245e8d8bef9SDimitry Andric   generateLoadForNewConst(unsigned Idx, MachineInstr *MI, Type *Ty,
246e8d8bef9SDimitry Andric                           SmallVectorImpl<MachineInstr *> &InsInstrs) const;
2470b57cec5SDimitry Andric   virtual void anchor();
2480b57cec5SDimitry Andric 
2490b57cec5SDimitry Andric protected:
2500b57cec5SDimitry Andric   /// Commutes the operands in the given instruction.
2510b57cec5SDimitry Andric   /// The commutable operands are specified by their indices OpIdx1 and OpIdx2.
2520b57cec5SDimitry Andric   ///
2530b57cec5SDimitry Andric   /// Do not call this method for a non-commutable instruction or for
2540b57cec5SDimitry Andric   /// non-commutable pair of operand indices OpIdx1 and OpIdx2.
2550b57cec5SDimitry Andric   /// Even though the instruction is commutable, the method may still
2560b57cec5SDimitry Andric   /// fail to commute the operands, null pointer is returned in such cases.
2570b57cec5SDimitry Andric   ///
2580b57cec5SDimitry Andric   /// For example, we can commute rlwimi instructions, but only if the
2590b57cec5SDimitry Andric   /// rotate amt is zero.  We also have to munge the immediates a bit.
2600b57cec5SDimitry Andric   MachineInstr *commuteInstructionImpl(MachineInstr &MI, bool NewMI,
2610b57cec5SDimitry Andric                                        unsigned OpIdx1,
2620b57cec5SDimitry Andric                                        unsigned OpIdx2) const override;
2630b57cec5SDimitry Andric 
2640b57cec5SDimitry Andric public:
2650b57cec5SDimitry Andric   explicit PPCInstrInfo(PPCSubtarget &STI);
2660b57cec5SDimitry Andric 
26706c3fb27SDimitry Andric   bool isLoadFromConstantPool(MachineInstr *I) const;
26806c3fb27SDimitry Andric   const Constant *getConstantFromConstantPool(MachineInstr *I) const;
26906c3fb27SDimitry Andric 
2700b57cec5SDimitry Andric   /// getRegisterInfo - TargetInstrInfo is a superset of MRegister info.  As
2710b57cec5SDimitry Andric   /// such, whenever a client has an instance of instruction info, it should
2720b57cec5SDimitry Andric   /// always be able to get register info as well (through this method).
2730b57cec5SDimitry Andric   ///
getRegisterInfo()2740b57cec5SDimitry Andric   const PPCRegisterInfo &getRegisterInfo() const { return RI; }
2750b57cec5SDimitry Andric 
isXFormMemOp(unsigned Opcode)2760b57cec5SDimitry Andric   bool isXFormMemOp(unsigned Opcode) const {
2770b57cec5SDimitry Andric     return get(Opcode).TSFlags & PPCII::XFormMemOp;
2780b57cec5SDimitry Andric   }
isPrefixed(unsigned Opcode)2795ffd83dbSDimitry Andric   bool isPrefixed(unsigned Opcode) const {
2805ffd83dbSDimitry Andric     return get(Opcode).TSFlags & PPCII::Prefixed;
2815ffd83dbSDimitry Andric   }
isSExt32To64(unsigned Opcode)282bdd1243dSDimitry Andric   bool isSExt32To64(unsigned Opcode) const {
283bdd1243dSDimitry Andric     return get(Opcode).TSFlags & PPCII::SExt32To64;
284bdd1243dSDimitry Andric   }
isZExt32To64(unsigned Opcode)285bdd1243dSDimitry Andric   bool isZExt32To64(unsigned Opcode) const {
286bdd1243dSDimitry Andric     return get(Opcode).TSFlags & PPCII::ZExt32To64;
287bdd1243dSDimitry Andric   }
2885ffd83dbSDimitry Andric 
isSameClassPhysRegCopy(unsigned Opcode)2890b57cec5SDimitry Andric   static bool isSameClassPhysRegCopy(unsigned Opcode) {
290e8d8bef9SDimitry Andric     unsigned CopyOpcodes[] = {PPC::OR,        PPC::OR8,   PPC::FMR,
291e8d8bef9SDimitry Andric                               PPC::VOR,       PPC::XXLOR, PPC::XXLORf,
292e8d8bef9SDimitry Andric                               PPC::XSCPSGNDP, PPC::MCRF,  PPC::CROR,
293e8d8bef9SDimitry Andric                               PPC::EVOR,      -1U};
2940b57cec5SDimitry Andric     for (int i = 0; CopyOpcodes[i] != -1U; i++)
2950b57cec5SDimitry Andric       if (Opcode == CopyOpcodes[i])
2960b57cec5SDimitry Andric         return true;
2970b57cec5SDimitry Andric     return false;
2980b57cec5SDimitry Andric   }
2990b57cec5SDimitry Andric 
hasPCRelFlag(unsigned TF)3005f757f3fSDimitry Andric   static bool hasPCRelFlag(unsigned TF) {
3015f757f3fSDimitry Andric     return TF == PPCII::MO_PCREL_FLAG || TF == PPCII::MO_GOT_TLSGD_PCREL_FLAG ||
3025f757f3fSDimitry Andric            TF == PPCII::MO_GOT_TLSLD_PCREL_FLAG ||
3035f757f3fSDimitry Andric            TF == PPCII::MO_GOT_TPREL_PCREL_FLAG ||
3045f757f3fSDimitry Andric            TF == PPCII::MO_TPREL_PCREL_FLAG || TF == PPCII::MO_TLS_PCREL_FLAG ||
3055f757f3fSDimitry Andric            TF == PPCII::MO_GOT_PCREL_FLAG;
3065f757f3fSDimitry Andric   }
3075f757f3fSDimitry Andric 
hasGOTFlag(unsigned TF)3085f757f3fSDimitry Andric   static bool hasGOTFlag(unsigned TF) {
3095f757f3fSDimitry Andric     return TF == PPCII::MO_GOT_FLAG || TF == PPCII::MO_GOT_TLSGD_PCREL_FLAG ||
3105f757f3fSDimitry Andric            TF == PPCII::MO_GOT_TLSLD_PCREL_FLAG ||
3115f757f3fSDimitry Andric            TF == PPCII::MO_GOT_TPREL_PCREL_FLAG ||
3125f757f3fSDimitry Andric            TF == PPCII::MO_GOT_PCREL_FLAG;
3135f757f3fSDimitry Andric   }
3145f757f3fSDimitry Andric 
hasTLSFlag(unsigned TF)3155f757f3fSDimitry Andric   static bool hasTLSFlag(unsigned TF) {
3165f757f3fSDimitry Andric     return TF == PPCII::MO_TLSGD_FLAG || TF == PPCII::MO_TPREL_FLAG ||
3175f757f3fSDimitry Andric            TF == PPCII::MO_TLSLD_FLAG || TF == PPCII::MO_TLSGDM_FLAG ||
3185f757f3fSDimitry Andric            TF == PPCII::MO_GOT_TLSGD_PCREL_FLAG ||
3195f757f3fSDimitry Andric            TF == PPCII::MO_GOT_TLSLD_PCREL_FLAG ||
3205f757f3fSDimitry Andric            TF == PPCII::MO_GOT_TPREL_PCREL_FLAG || TF == PPCII::MO_TPREL_LO ||
3215f757f3fSDimitry Andric            TF == PPCII::MO_TPREL_HA || TF == PPCII::MO_DTPREL_LO ||
3225f757f3fSDimitry Andric            TF == PPCII::MO_TLSLD_LO || TF == PPCII::MO_TLS ||
3235f757f3fSDimitry Andric            TF == PPCII::MO_TPREL_PCREL_FLAG || TF == PPCII::MO_TLS_PCREL_FLAG;
3245f757f3fSDimitry Andric   }
3255f757f3fSDimitry Andric 
3260b57cec5SDimitry Andric   ScheduleHazardRecognizer *
3270b57cec5SDimitry Andric   CreateTargetHazardRecognizer(const TargetSubtargetInfo *STI,
3280b57cec5SDimitry Andric                                const ScheduleDAG *DAG) const override;
3290b57cec5SDimitry Andric   ScheduleHazardRecognizer *
3300b57cec5SDimitry Andric   CreateTargetPostRAHazardRecognizer(const InstrItineraryData *II,
3310b57cec5SDimitry Andric                                      const ScheduleDAG *DAG) const override;
3320b57cec5SDimitry Andric 
3330b57cec5SDimitry Andric   unsigned getInstrLatency(const InstrItineraryData *ItinData,
3340b57cec5SDimitry Andric                            const MachineInstr &MI,
3350b57cec5SDimitry Andric                            unsigned *PredCost = nullptr) const override;
3360b57cec5SDimitry Andric 
3375f757f3fSDimitry Andric   std::optional<unsigned> getOperandLatency(const InstrItineraryData *ItinData,
3385f757f3fSDimitry Andric                                             const MachineInstr &DefMI,
3395f757f3fSDimitry Andric                                             unsigned DefIdx,
3400b57cec5SDimitry Andric                                             const MachineInstr &UseMI,
3410b57cec5SDimitry Andric                                             unsigned UseIdx) const override;
getOperandLatency(const InstrItineraryData * ItinData,SDNode * DefNode,unsigned DefIdx,SDNode * UseNode,unsigned UseIdx)3425f757f3fSDimitry Andric   std::optional<unsigned> getOperandLatency(const InstrItineraryData *ItinData,
3430b57cec5SDimitry Andric                                             SDNode *DefNode, unsigned DefIdx,
3445f757f3fSDimitry Andric                                             SDNode *UseNode,
3455f757f3fSDimitry Andric                                             unsigned UseIdx) const override {
3460b57cec5SDimitry Andric     return PPCGenInstrInfo::getOperandLatency(ItinData, DefNode, DefIdx,
3470b57cec5SDimitry Andric                                               UseNode, UseIdx);
3480b57cec5SDimitry Andric   }
3490b57cec5SDimitry Andric 
hasLowDefLatency(const TargetSchedModel & SchedModel,const MachineInstr & DefMI,unsigned DefIdx)3500b57cec5SDimitry Andric   bool hasLowDefLatency(const TargetSchedModel &SchedModel,
3510b57cec5SDimitry Andric                         const MachineInstr &DefMI,
3520b57cec5SDimitry Andric                         unsigned DefIdx) const override {
3530b57cec5SDimitry Andric     // Machine LICM should hoist all instructions in low-register-pressure
3540b57cec5SDimitry Andric     // situations; none are sufficiently free to justify leaving in a loop
3550b57cec5SDimitry Andric     // body.
3560b57cec5SDimitry Andric     return false;
3570b57cec5SDimitry Andric   }
3580b57cec5SDimitry Andric 
useMachineCombiner()3590b57cec5SDimitry Andric   bool useMachineCombiner() const override {
3600b57cec5SDimitry Andric     return true;
3610b57cec5SDimitry Andric   }
3620b57cec5SDimitry Andric 
3635ffd83dbSDimitry Andric   /// When getMachineCombinerPatterns() finds patterns, this function generates
3645ffd83dbSDimitry Andric   /// the instructions that could replace the original code sequence
3655ffd83dbSDimitry Andric   void genAlternativeCodeSequence(
366*0fca6ea1SDimitry Andric       MachineInstr &Root, unsigned Pattern,
3675ffd83dbSDimitry Andric       SmallVectorImpl<MachineInstr *> &InsInstrs,
3685ffd83dbSDimitry Andric       SmallVectorImpl<MachineInstr *> &DelInstrs,
3695ffd83dbSDimitry Andric       DenseMap<unsigned, unsigned> &InstrIdxForVirtReg) const override;
3705ffd83dbSDimitry Andric 
3715ffd83dbSDimitry Andric   /// Return true when there is potentially a faster code sequence for a fma
3725ffd83dbSDimitry Andric   /// chain ending in \p Root. All potential patterns are output in the \p
3735ffd83dbSDimitry Andric   /// P array.
374*0fca6ea1SDimitry Andric   bool getFMAPatterns(MachineInstr &Root, SmallVectorImpl<unsigned> &Patterns,
375e8d8bef9SDimitry Andric                       bool DoRegPressureReduce) const;
3765ffd83dbSDimitry Andric 
377*0fca6ea1SDimitry Andric   CombinerObjective getCombinerObjective(unsigned Pattern) const override;
378*0fca6ea1SDimitry Andric 
3790b57cec5SDimitry Andric   /// Return true when there is potentially a faster code sequence
3800b57cec5SDimitry Andric   /// for an instruction chain ending in <Root>. All potential patterns are
3810b57cec5SDimitry Andric   /// output in the <Pattern> array.
382e8d8bef9SDimitry Andric   bool getMachineCombinerPatterns(MachineInstr &Root,
383*0fca6ea1SDimitry Andric                                   SmallVectorImpl<unsigned> &Patterns,
384e8d8bef9SDimitry Andric                                   bool DoRegPressureReduce) const override;
385e8d8bef9SDimitry Andric 
386e8d8bef9SDimitry Andric   /// On PowerPC, we leverage machine combiner pass to reduce register pressure
387e8d8bef9SDimitry Andric   /// when the register pressure is high for one BB.
388e8d8bef9SDimitry Andric   /// Return true if register pressure for \p MBB is high and ABI is supported
389e8d8bef9SDimitry Andric   /// to reduce register pressure. Otherwise return false.
390bdd1243dSDimitry Andric   bool shouldReduceRegisterPressure(
391bdd1243dSDimitry Andric       const MachineBasicBlock *MBB,
392bdd1243dSDimitry Andric       const RegisterClassInfo *RegClassInfo) const override;
393e8d8bef9SDimitry Andric 
394e8d8bef9SDimitry Andric   /// Fixup the placeholders we put in genAlternativeCodeSequence() for
395e8d8bef9SDimitry Andric   /// MachineCombiner.
396e8d8bef9SDimitry Andric   void
397*0fca6ea1SDimitry Andric   finalizeInsInstrs(MachineInstr &Root, unsigned &Pattern,
398e8d8bef9SDimitry Andric                     SmallVectorImpl<MachineInstr *> &InsInstrs) const override;
3990b57cec5SDimitry Andric 
400bdd1243dSDimitry Andric   bool isAssociativeAndCommutative(const MachineInstr &Inst,
401bdd1243dSDimitry Andric                                    bool Invert) const override;
4020b57cec5SDimitry Andric 
4035ffd83dbSDimitry Andric   /// On PowerPC, we try to reassociate FMA chain which will increase
4045ffd83dbSDimitry Andric   /// instruction size. Set extension resource length limit to 1 for edge case.
4055ffd83dbSDimitry Andric   /// Resource Length is calculated by scaled resource usage in getCycles().
4065ffd83dbSDimitry Andric   /// Because of the division in getCycles(), it returns different cycles due to
4075ffd83dbSDimitry Andric   /// legacy scaled resource usage. So new resource length may be same with
4085ffd83dbSDimitry Andric   /// legacy or 1 bigger than legacy.
4095ffd83dbSDimitry Andric   /// We need to execlude the 1 bigger case even the resource length is not
4105ffd83dbSDimitry Andric   /// perserved for more FMA chain reassociations on PowerPC.
getExtendResourceLenLimit()4115ffd83dbSDimitry Andric   int getExtendResourceLenLimit() const override { return 1; }
4125ffd83dbSDimitry Andric 
4130eae32dcSDimitry Andric   // PowerPC specific version of setSpecialOperandAttr that copies Flags to MI
4140eae32dcSDimitry Andric   // and clears nuw, nsw, and exact flags.
4155f757f3fSDimitry Andric   using TargetInstrInfo::setSpecialOperandAttr;
41606c3fb27SDimitry Andric   void setSpecialOperandAttr(MachineInstr &MI, uint32_t Flags) const;
4175ffd83dbSDimitry Andric 
4180b57cec5SDimitry Andric   bool isCoalescableExtInstr(const MachineInstr &MI,
4195ffd83dbSDimitry Andric                              Register &SrcReg, Register &DstReg,
4200b57cec5SDimitry Andric                              unsigned &SubIdx) const override;
421*0fca6ea1SDimitry Andric   Register isLoadFromStackSlot(const MachineInstr &MI,
4220b57cec5SDimitry Andric                                int &FrameIndex) const override;
423fcaf7f86SDimitry Andric   bool isReallyTriviallyReMaterializable(const MachineInstr &MI) const override;
424*0fca6ea1SDimitry Andric   Register isStoreToStackSlot(const MachineInstr &MI,
4250b57cec5SDimitry Andric                               int &FrameIndex) const override;
4260b57cec5SDimitry Andric 
4278bcb0991SDimitry Andric   bool findCommutedOpIndices(const MachineInstr &MI, unsigned &SrcOpIdx1,
4280b57cec5SDimitry Andric                              unsigned &SrcOpIdx2) const override;
4290b57cec5SDimitry Andric 
4300b57cec5SDimitry Andric   void insertNoop(MachineBasicBlock &MBB,
4310b57cec5SDimitry Andric                   MachineBasicBlock::iterator MI) const override;
4320b57cec5SDimitry Andric 
4330b57cec5SDimitry Andric 
4340b57cec5SDimitry Andric   // Branch analysis.
4350b57cec5SDimitry Andric   bool analyzeBranch(MachineBasicBlock &MBB, MachineBasicBlock *&TBB,
4360b57cec5SDimitry Andric                      MachineBasicBlock *&FBB,
4370b57cec5SDimitry Andric                      SmallVectorImpl<MachineOperand> &Cond,
4380b57cec5SDimitry Andric                      bool AllowModify) const override;
4390b57cec5SDimitry Andric   unsigned removeBranch(MachineBasicBlock &MBB,
4400b57cec5SDimitry Andric                         int *BytesRemoved = nullptr) const override;
4410b57cec5SDimitry Andric   unsigned insertBranch(MachineBasicBlock &MBB, MachineBasicBlock *TBB,
4420b57cec5SDimitry Andric                         MachineBasicBlock *FBB, ArrayRef<MachineOperand> Cond,
4430b57cec5SDimitry Andric                         const DebugLoc &DL,
4440b57cec5SDimitry Andric                         int *BytesAdded = nullptr) const override;
4450b57cec5SDimitry Andric 
4460b57cec5SDimitry Andric   // Select analysis.
4470b57cec5SDimitry Andric   bool canInsertSelect(const MachineBasicBlock &, ArrayRef<MachineOperand> Cond,
4485ffd83dbSDimitry Andric                        Register, Register, Register, int &, int &,
4495ffd83dbSDimitry Andric                        int &) const override;
4500b57cec5SDimitry Andric   void insertSelect(MachineBasicBlock &MBB, MachineBasicBlock::iterator MI,
4515ffd83dbSDimitry Andric                     const DebugLoc &DL, Register DstReg,
4525ffd83dbSDimitry Andric                     ArrayRef<MachineOperand> Cond, Register TrueReg,
4535ffd83dbSDimitry Andric                     Register FalseReg) const override;
4540b57cec5SDimitry Andric 
4550b57cec5SDimitry Andric   void copyPhysReg(MachineBasicBlock &MBB, MachineBasicBlock::iterator I,
456480093f4SDimitry Andric                    const DebugLoc &DL, MCRegister DestReg, MCRegister SrcReg,
4570b57cec5SDimitry Andric                    bool KillSrc) const override;
4580b57cec5SDimitry Andric 
4590b57cec5SDimitry Andric   void storeRegToStackSlot(MachineBasicBlock &MBB,
460bdd1243dSDimitry Andric                            MachineBasicBlock::iterator MBBI, Register SrcReg,
461bdd1243dSDimitry Andric                            bool isKill, int FrameIndex,
4620b57cec5SDimitry Andric                            const TargetRegisterClass *RC,
463bdd1243dSDimitry Andric                            const TargetRegisterInfo *TRI,
464bdd1243dSDimitry Andric                            Register VReg) const override;
4650b57cec5SDimitry Andric 
4665ffd83dbSDimitry Andric   // Emits a register spill without updating the register class for vector
4675ffd83dbSDimitry Andric   // registers. This ensures that when we spill a vector register the
4685ffd83dbSDimitry Andric   // element order in the register is the same as it was in memory.
4695ffd83dbSDimitry Andric   void storeRegToStackSlotNoUpd(MachineBasicBlock &MBB,
4705ffd83dbSDimitry Andric                                 MachineBasicBlock::iterator MBBI,
4715ffd83dbSDimitry Andric                                 unsigned SrcReg, bool isKill, int FrameIndex,
4725ffd83dbSDimitry Andric                                 const TargetRegisterClass *RC,
4735ffd83dbSDimitry Andric                                 const TargetRegisterInfo *TRI) const;
4745ffd83dbSDimitry Andric 
4750b57cec5SDimitry Andric   void loadRegFromStackSlot(MachineBasicBlock &MBB,
476bdd1243dSDimitry Andric                             MachineBasicBlock::iterator MBBI, Register DestReg,
477bdd1243dSDimitry Andric                             int FrameIndex, const TargetRegisterClass *RC,
478bdd1243dSDimitry Andric                             const TargetRegisterInfo *TRI,
479bdd1243dSDimitry Andric                             Register VReg) const override;
4800b57cec5SDimitry Andric 
4815ffd83dbSDimitry Andric   // Emits a register reload without updating the register class for vector
4825ffd83dbSDimitry Andric   // registers. This ensures that when we reload a vector register the
4835ffd83dbSDimitry Andric   // element order in the register is the same as it was in memory.
4845ffd83dbSDimitry Andric   void loadRegFromStackSlotNoUpd(MachineBasicBlock &MBB,
4855ffd83dbSDimitry Andric                                  MachineBasicBlock::iterator MBBI,
4865ffd83dbSDimitry Andric                                  unsigned DestReg, int FrameIndex,
4875ffd83dbSDimitry Andric                                  const TargetRegisterClass *RC,
4885ffd83dbSDimitry Andric                                  const TargetRegisterInfo *TRI) const;
4890b57cec5SDimitry Andric 
4905ffd83dbSDimitry Andric   unsigned getStoreOpcodeForSpill(const TargetRegisterClass *RC) const;
4915ffd83dbSDimitry Andric 
4925ffd83dbSDimitry Andric   unsigned getLoadOpcodeForSpill(const TargetRegisterClass *RC) const;
4930b57cec5SDimitry Andric 
4940b57cec5SDimitry Andric   bool
4950b57cec5SDimitry Andric   reverseBranchCondition(SmallVectorImpl<MachineOperand> &Cond) const override;
4960b57cec5SDimitry Andric 
497*0fca6ea1SDimitry Andric   bool foldImmediate(MachineInstr &UseMI, MachineInstr &DefMI, Register Reg,
4980b57cec5SDimitry Andric                      MachineRegisterInfo *MRI) const override;
4990b57cec5SDimitry Andric 
5005ffd83dbSDimitry Andric   bool onlyFoldImmediate(MachineInstr &UseMI, MachineInstr &DefMI,
5015ffd83dbSDimitry Andric                          Register Reg) const;
5025ffd83dbSDimitry Andric 
5030b57cec5SDimitry Andric   // If conversion by predication (only supported by some branch instructions).
5040b57cec5SDimitry Andric   // All of the profitability checks always return true; it is always
5050b57cec5SDimitry Andric   // profitable to use the predicated branches.
isProfitableToIfCvt(MachineBasicBlock & MBB,unsigned NumCycles,unsigned ExtraPredCycles,BranchProbability Probability)5060b57cec5SDimitry Andric   bool isProfitableToIfCvt(MachineBasicBlock &MBB,
5070b57cec5SDimitry Andric                           unsigned NumCycles, unsigned ExtraPredCycles,
5080b57cec5SDimitry Andric                           BranchProbability Probability) const override {
5090b57cec5SDimitry Andric     return true;
5100b57cec5SDimitry Andric   }
5110b57cec5SDimitry Andric 
5120b57cec5SDimitry Andric   bool isProfitableToIfCvt(MachineBasicBlock &TMBB,
5130b57cec5SDimitry Andric                            unsigned NumT, unsigned ExtraT,
5140b57cec5SDimitry Andric                            MachineBasicBlock &FMBB,
5150b57cec5SDimitry Andric                            unsigned NumF, unsigned ExtraF,
5160b57cec5SDimitry Andric                            BranchProbability Probability) const override;
5170b57cec5SDimitry Andric 
isProfitableToDupForIfCvt(MachineBasicBlock & MBB,unsigned NumCycles,BranchProbability Probability)5180b57cec5SDimitry Andric   bool isProfitableToDupForIfCvt(MachineBasicBlock &MBB, unsigned NumCycles,
5190b57cec5SDimitry Andric                                  BranchProbability Probability) const override {
5200b57cec5SDimitry Andric     return true;
5210b57cec5SDimitry Andric   }
5220b57cec5SDimitry Andric 
isProfitableToUnpredicate(MachineBasicBlock & TMBB,MachineBasicBlock & FMBB)5230b57cec5SDimitry Andric   bool isProfitableToUnpredicate(MachineBasicBlock &TMBB,
5240b57cec5SDimitry Andric                                  MachineBasicBlock &FMBB) const override {
5250b57cec5SDimitry Andric     return false;
5260b57cec5SDimitry Andric   }
5270b57cec5SDimitry Andric 
5280b57cec5SDimitry Andric   // Predication support.
5290b57cec5SDimitry Andric   bool isPredicated(const MachineInstr &MI) const override;
5300b57cec5SDimitry Andric 
531e8d8bef9SDimitry Andric   bool isSchedulingBoundary(const MachineInstr &MI,
532e8d8bef9SDimitry Andric                             const MachineBasicBlock *MBB,
533e8d8bef9SDimitry Andric                             const MachineFunction &MF) const override;
534e8d8bef9SDimitry Andric 
5350b57cec5SDimitry Andric   bool PredicateInstruction(MachineInstr &MI,
5360b57cec5SDimitry Andric                             ArrayRef<MachineOperand> Pred) const override;
5370b57cec5SDimitry Andric 
5380b57cec5SDimitry Andric   bool SubsumesPredicate(ArrayRef<MachineOperand> Pred1,
5390b57cec5SDimitry Andric                          ArrayRef<MachineOperand> Pred2) const override;
5400b57cec5SDimitry Andric 
541e8d8bef9SDimitry Andric   bool ClobbersPredicate(MachineInstr &MI, std::vector<MachineOperand> &Pred,
542e8d8bef9SDimitry Andric                          bool SkipDead) const override;
5430b57cec5SDimitry Andric 
5440b57cec5SDimitry Andric   // Comparison optimization.
5450b57cec5SDimitry Andric 
5465ffd83dbSDimitry Andric   bool analyzeCompare(const MachineInstr &MI, Register &SrcReg,
547349cc55cSDimitry Andric                       Register &SrcReg2, int64_t &Mask,
548349cc55cSDimitry Andric                       int64_t &Value) const override;
5490b57cec5SDimitry Andric 
5505ffd83dbSDimitry Andric   bool optimizeCompareInstr(MachineInstr &CmpInstr, Register SrcReg,
551349cc55cSDimitry Andric                             Register SrcReg2, int64_t Mask, int64_t Value,
5520b57cec5SDimitry Andric                             const MachineRegisterInfo *MRI) const override;
5530b57cec5SDimitry Andric 
5540b57cec5SDimitry Andric 
5550b57cec5SDimitry Andric   /// Return true if get the base operand, byte offset of an instruction and
5560b57cec5SDimitry Andric   /// the memory width. Width is the size of memory that is being
5570b57cec5SDimitry Andric   /// loaded/stored (e.g. 1, 2, 4, 8).
5580b57cec5SDimitry Andric   bool getMemOperandWithOffsetWidth(const MachineInstr &LdSt,
5590b57cec5SDimitry Andric                                     const MachineOperand *&BaseOp,
560*0fca6ea1SDimitry Andric                                     int64_t &Offset, LocationSize &Width,
5610b57cec5SDimitry Andric                                     const TargetRegisterInfo *TRI) const;
5620b57cec5SDimitry Andric 
563bdd1243dSDimitry Andric   bool optimizeCmpPostRA(MachineInstr &MI) const;
564bdd1243dSDimitry Andric 
565e8d8bef9SDimitry Andric   /// Get the base operand and byte offset of an instruction that reads/writes
566e8d8bef9SDimitry Andric   /// memory.
567e8d8bef9SDimitry Andric   bool getMemOperandsWithOffsetWidth(
568e8d8bef9SDimitry Andric       const MachineInstr &LdSt,
569e8d8bef9SDimitry Andric       SmallVectorImpl<const MachineOperand *> &BaseOps, int64_t &Offset,
570*0fca6ea1SDimitry Andric       bool &OffsetIsScalable, LocationSize &Width,
571e8d8bef9SDimitry Andric       const TargetRegisterInfo *TRI) const override;
572e8d8bef9SDimitry Andric 
573e8d8bef9SDimitry Andric   /// Returns true if the two given memory operations should be scheduled
574e8d8bef9SDimitry Andric   /// adjacent.
575e8d8bef9SDimitry Andric   bool shouldClusterMemOps(ArrayRef<const MachineOperand *> BaseOps1,
5765f757f3fSDimitry Andric                            int64_t Offset1, bool OffsetIsScalable1,
577e8d8bef9SDimitry Andric                            ArrayRef<const MachineOperand *> BaseOps2,
5785f757f3fSDimitry Andric                            int64_t Offset2, bool OffsetIsScalable2,
5795f757f3fSDimitry Andric                            unsigned ClusterSize,
5805f757f3fSDimitry Andric                            unsigned NumBytes) const override;
581e8d8bef9SDimitry Andric 
5820b57cec5SDimitry Andric   /// Return true if two MIs access different memory addresses and false
5830b57cec5SDimitry Andric   /// otherwise
5840b57cec5SDimitry Andric   bool
5850b57cec5SDimitry Andric   areMemAccessesTriviallyDisjoint(const MachineInstr &MIa,
5868bcb0991SDimitry Andric                                   const MachineInstr &MIb) const override;
5870b57cec5SDimitry Andric 
5880b57cec5SDimitry Andric   /// GetInstSize - Return the number of bytes of code the specified
5890b57cec5SDimitry Andric   /// instruction may be.  This returns the maximum number of bytes.
5900b57cec5SDimitry Andric   ///
5910b57cec5SDimitry Andric   unsigned getInstSizeInBytes(const MachineInstr &MI) const override;
5920b57cec5SDimitry Andric 
593fe6060f1SDimitry Andric   MCInst getNop() const override;
5940b57cec5SDimitry Andric 
5950b57cec5SDimitry Andric   std::pair<unsigned, unsigned>
5960b57cec5SDimitry Andric   decomposeMachineOperandsTargetFlags(unsigned TF) const override;
5970b57cec5SDimitry Andric 
5980b57cec5SDimitry Andric   ArrayRef<std::pair<unsigned, const char *>>
5990b57cec5SDimitry Andric   getSerializableDirectMachineOperandTargetFlags() const override;
6000b57cec5SDimitry Andric 
6010b57cec5SDimitry Andric   // Expand VSX Memory Pseudo instruction to either a VSX or a FP instruction.
6020b57cec5SDimitry Andric   bool expandVSXMemPseudo(MachineInstr &MI) const;
6030b57cec5SDimitry Andric 
6040b57cec5SDimitry Andric   // Lower pseudo instructions after register allocation.
6050b57cec5SDimitry Andric   bool expandPostRAPseudo(MachineInstr &MI) const override;
6060b57cec5SDimitry Andric 
6070b57cec5SDimitry Andric   const TargetRegisterClass *updatedRC(const TargetRegisterClass *RC) const;
6080b57cec5SDimitry Andric   static int getRecordFormOpcode(unsigned Opcode);
6090b57cec5SDimitry Andric 
6100b57cec5SDimitry Andric   bool isTOCSaveMI(const MachineInstr &MI) const;
6110b57cec5SDimitry Andric 
612bdd1243dSDimitry Andric   std::pair<bool, bool>
613bdd1243dSDimitry Andric   isSignOrZeroExtended(const unsigned Reg, const unsigned BinOpDepth,
614bdd1243dSDimitry Andric                        const MachineRegisterInfo *MRI) const;
6150b57cec5SDimitry Andric 
616bdd1243dSDimitry Andric   // Return true if the register is sign-extended from 32 to 64 bits.
isSignExtended(const unsigned Reg,const MachineRegisterInfo * MRI)617bdd1243dSDimitry Andric   bool isSignExtended(const unsigned Reg,
618bdd1243dSDimitry Andric                       const MachineRegisterInfo *MRI) const {
619bdd1243dSDimitry Andric     return isSignOrZeroExtended(Reg, 0, MRI).first;
6200b57cec5SDimitry Andric   }
6210b57cec5SDimitry Andric 
622bdd1243dSDimitry Andric   // Return true if the register is zero-extended from 32 to 64 bits.
isZeroExtended(const unsigned Reg,const MachineRegisterInfo * MRI)623bdd1243dSDimitry Andric   bool isZeroExtended(const unsigned Reg,
624bdd1243dSDimitry Andric                       const MachineRegisterInfo *MRI) const {
625bdd1243dSDimitry Andric     return isSignOrZeroExtended(Reg, 0, MRI).second;
6260b57cec5SDimitry Andric   }
6270b57cec5SDimitry Andric 
6280b57cec5SDimitry Andric   bool convertToImmediateForm(MachineInstr &MI,
6295f757f3fSDimitry Andric                               SmallSet<Register, 4> &RegsToUpdate,
6300b57cec5SDimitry Andric                               MachineInstr **KilledDef = nullptr) const;
631480093f4SDimitry Andric   bool foldFrameOffset(MachineInstr &MI) const;
632e8d8bef9SDimitry Andric   bool combineRLWINM(MachineInstr &MI, MachineInstr **ToErase = nullptr) const;
633480093f4SDimitry Andric   bool isADDIInstrEligibleForFolding(MachineInstr &ADDIMI, int64_t &Imm) const;
634480093f4SDimitry Andric   bool isADDInstrEligibleForFolding(MachineInstr &ADDMI) const;
635480093f4SDimitry Andric   bool isImmInstrEligibleForFolding(MachineInstr &MI, unsigned &BaseReg,
636480093f4SDimitry Andric                                     unsigned &XFormOpcode,
637480093f4SDimitry Andric                                     int64_t &OffsetOfImmInstr,
638480093f4SDimitry Andric                                     ImmInstrInfo &III) const;
639480093f4SDimitry Andric   bool isValidToBeChangedReg(MachineInstr *ADDMI, unsigned Index,
640480093f4SDimitry Andric                              MachineInstr *&ADDIMI, int64_t &OffsetAddi,
641480093f4SDimitry Andric                              int64_t OffsetImm) const;
6420b57cec5SDimitry Andric 
6430b57cec5SDimitry Andric   void replaceInstrWithLI(MachineInstr &MI, const LoadImmediateInfo &LII) const;
6440b57cec5SDimitry Andric   void replaceInstrOperandWithImm(MachineInstr &MI, unsigned OpNo,
6450b57cec5SDimitry Andric                                   int64_t Imm) const;
6460b57cec5SDimitry Andric 
6478bcb0991SDimitry Andric   bool instrHasImmForm(unsigned Opc, bool IsVFReg, ImmInstrInfo &III,
6480b57cec5SDimitry Andric                        bool PostRA) const;
6490b57cec5SDimitry Andric 
6508bcb0991SDimitry Andric   // In PostRA phase, try to find instruction defines \p Reg before \p MI.
6518bcb0991SDimitry Andric   // \p SeenIntermediate is set to true if uses between DefMI and \p MI exist.
6528bcb0991SDimitry Andric   MachineInstr *getDefMIPostRA(unsigned Reg, MachineInstr &MI,
6538bcb0991SDimitry Andric                                bool &SeenIntermediateUse) const;
6548bcb0991SDimitry Andric 
65581ad6265SDimitry Andric   // Materialize immediate after RA.
65681ad6265SDimitry Andric   void materializeImmPostRA(MachineBasicBlock &MBB,
65781ad6265SDimitry Andric                             MachineBasicBlock::iterator MBBI,
65881ad6265SDimitry Andric                             const DebugLoc &DL, Register Reg,
65981ad6265SDimitry Andric                             int64_t Imm) const;
66081ad6265SDimitry Andric 
6610b57cec5SDimitry Andric   /// Check \p Opcode is BDNZ (Decrement CTR and branch if it is still nonzero).
6620b57cec5SDimitry Andric   bool isBDNZ(unsigned Opcode) const;
6630b57cec5SDimitry Andric 
6640b57cec5SDimitry Andric   /// Find the hardware loop instruction used to set-up the specified loop.
6650b57cec5SDimitry Andric   /// On PPC, we have two instructions used to set-up the hardware loop
6660b57cec5SDimitry Andric   /// (MTCTRloop, MTCTR8loop) with corresponding endloop (BDNZ, BDNZ8)
6670b57cec5SDimitry Andric   /// instructions to indicate the end of a loop.
6688bcb0991SDimitry Andric   MachineInstr *
6698bcb0991SDimitry Andric   findLoopInstr(MachineBasicBlock &PreHeader,
6708bcb0991SDimitry Andric                 SmallPtrSet<MachineBasicBlock *, 8> &Visited) const;
6710b57cec5SDimitry Andric 
6728bcb0991SDimitry Andric   /// Analyze loop L, which must be a single-basic-block loop, and if the
6738bcb0991SDimitry Andric   /// conditions can be understood enough produce a PipelinerLoopInfo object.
6748bcb0991SDimitry Andric   std::unique_ptr<TargetInstrInfo::PipelinerLoopInfo>
6758bcb0991SDimitry Andric   analyzeLoopForPipelining(MachineBasicBlock *LoopBB) const override;
6760b57cec5SDimitry Andric };
6770b57cec5SDimitry Andric 
6780b57cec5SDimitry Andric }
6790b57cec5SDimitry Andric 
6800b57cec5SDimitry Andric #endif
681