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