10b57cec5SDimitry Andric //===-- SystemZInstrInfo.h - SystemZ 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 SystemZ implementation of the TargetInstrInfo class.
100b57cec5SDimitry Andric //
110b57cec5SDimitry Andric //===----------------------------------------------------------------------===//
120b57cec5SDimitry Andric 
130b57cec5SDimitry Andric #ifndef LLVM_LIB_TARGET_SYSTEMZ_SYSTEMZINSTRINFO_H
140b57cec5SDimitry Andric #define LLVM_LIB_TARGET_SYSTEMZ_SYSTEMZINSTRINFO_H
150b57cec5SDimitry Andric 
160b57cec5SDimitry Andric #include "SystemZ.h"
170b57cec5SDimitry Andric #include "SystemZRegisterInfo.h"
180b57cec5SDimitry Andric #include "llvm/ADT/ArrayRef.h"
190b57cec5SDimitry Andric #include "llvm/CodeGen/MachineBasicBlock.h"
200b57cec5SDimitry Andric #include "llvm/CodeGen/MachineFunction.h"
210b57cec5SDimitry Andric #include "llvm/CodeGen/MachineInstrBuilder.h"
220b57cec5SDimitry Andric #include "llvm/CodeGen/TargetInstrInfo.h"
230b57cec5SDimitry Andric #include <cstdint>
240b57cec5SDimitry Andric 
250b57cec5SDimitry Andric #define GET_INSTRINFO_HEADER
260b57cec5SDimitry Andric #include "SystemZGenInstrInfo.inc"
270b57cec5SDimitry Andric 
280b57cec5SDimitry Andric namespace llvm {
290b57cec5SDimitry Andric 
300b57cec5SDimitry Andric class SystemZSubtarget;
310b57cec5SDimitry Andric 
320b57cec5SDimitry Andric namespace SystemZII {
330b57cec5SDimitry Andric 
340b57cec5SDimitry Andric enum {
350b57cec5SDimitry Andric   // See comments in SystemZInstrFormats.td.
360b57cec5SDimitry Andric   SimpleBDXLoad          = (1 << 0),
370b57cec5SDimitry Andric   SimpleBDXStore         = (1 << 1),
380b57cec5SDimitry Andric   Has20BitOffset         = (1 << 2),
390b57cec5SDimitry Andric   HasIndex               = (1 << 3),
400b57cec5SDimitry Andric   Is128Bit               = (1 << 4),
410b57cec5SDimitry Andric   AccessSizeMask         = (31 << 5),
420b57cec5SDimitry Andric   AccessSizeShift        = 5,
430b57cec5SDimitry Andric   CCValuesMask           = (15 << 10),
440b57cec5SDimitry Andric   CCValuesShift          = 10,
450b57cec5SDimitry Andric   CompareZeroCCMaskMask  = (15 << 14),
460b57cec5SDimitry Andric   CompareZeroCCMaskShift = 14,
470b57cec5SDimitry Andric   CCMaskFirst            = (1 << 18),
480b57cec5SDimitry Andric   CCMaskLast             = (1 << 19),
49480093f4SDimitry Andric   IsLogical              = (1 << 20),
5081ad6265SDimitry Andric   CCIfNoSignedWrap       = (1 << 21)
510b57cec5SDimitry Andric };
520b57cec5SDimitry Andric 
getAccessSize(unsigned int Flags)530b57cec5SDimitry Andric static inline unsigned getAccessSize(unsigned int Flags) {
540b57cec5SDimitry Andric   return (Flags & AccessSizeMask) >> AccessSizeShift;
550b57cec5SDimitry Andric }
560b57cec5SDimitry Andric 
getCCValues(unsigned int Flags)570b57cec5SDimitry Andric static inline unsigned getCCValues(unsigned int Flags) {
580b57cec5SDimitry Andric   return (Flags & CCValuesMask) >> CCValuesShift;
590b57cec5SDimitry Andric }
600b57cec5SDimitry Andric 
getCompareZeroCCMask(unsigned int Flags)610b57cec5SDimitry Andric static inline unsigned getCompareZeroCCMask(unsigned int Flags) {
620b57cec5SDimitry Andric   return (Flags & CompareZeroCCMaskMask) >> CompareZeroCCMaskShift;
630b57cec5SDimitry Andric }
640b57cec5SDimitry Andric 
650b57cec5SDimitry Andric // SystemZ MachineOperand target flags.
660b57cec5SDimitry Andric enum {
670b57cec5SDimitry Andric   // Masks out the bits for the access model.
680b57cec5SDimitry Andric   MO_SYMBOL_MODIFIER = (3 << 0),
690b57cec5SDimitry Andric 
700b57cec5SDimitry Andric   // @GOT (aka @GOTENT)
710b57cec5SDimitry Andric   MO_GOT = (1 << 0),
720b57cec5SDimitry Andric 
730b57cec5SDimitry Andric   // @INDNTPOFF
740b57cec5SDimitry Andric   MO_INDNTPOFF = (2 << 0)
750b57cec5SDimitry Andric };
760b57cec5SDimitry Andric 
7706c3fb27SDimitry Andric // z/OS XPLink specific: classifies the types of
7806c3fb27SDimitry Andric // accesses to the ADA (Associated Data Area).
7906c3fb27SDimitry Andric // These enums contains values that overlap with the above MO_ enums,
8006c3fb27SDimitry Andric // but that's fine since the above enums are used with ELF,
8106c3fb27SDimitry Andric // while these values are used with z/OS.
8206c3fb27SDimitry Andric enum {
8306c3fb27SDimitry Andric   MO_ADA_DATA_SYMBOL_ADDR = 1,
8406c3fb27SDimitry Andric   MO_ADA_INDIRECT_FUNC_DESC,
8506c3fb27SDimitry Andric   MO_ADA_DIRECT_FUNC_DESC,
8606c3fb27SDimitry Andric };
8706c3fb27SDimitry Andric 
880b57cec5SDimitry Andric // Classifies a branch.
890b57cec5SDimitry Andric enum BranchType {
900b57cec5SDimitry Andric   // An instruction that branches on the current value of CC.
910b57cec5SDimitry Andric   BranchNormal,
920b57cec5SDimitry Andric 
930b57cec5SDimitry Andric   // An instruction that peforms a 32-bit signed comparison and branches
940b57cec5SDimitry Andric   // on the result.
950b57cec5SDimitry Andric   BranchC,
960b57cec5SDimitry Andric 
970b57cec5SDimitry Andric   // An instruction that peforms a 32-bit unsigned comparison and branches
980b57cec5SDimitry Andric   // on the result.
990b57cec5SDimitry Andric   BranchCL,
1000b57cec5SDimitry Andric 
1010b57cec5SDimitry Andric   // An instruction that peforms a 64-bit signed comparison and branches
1020b57cec5SDimitry Andric   // on the result.
1030b57cec5SDimitry Andric   BranchCG,
1040b57cec5SDimitry Andric 
1050b57cec5SDimitry Andric   // An instruction that peforms a 64-bit unsigned comparison and branches
1060b57cec5SDimitry Andric   // on the result.
1070b57cec5SDimitry Andric   BranchCLG,
1080b57cec5SDimitry Andric 
1090b57cec5SDimitry Andric   // An instruction that decrements a 32-bit register and branches if
1100b57cec5SDimitry Andric   // the result is nonzero.
1110b57cec5SDimitry Andric   BranchCT,
1120b57cec5SDimitry Andric 
1130b57cec5SDimitry Andric   // An instruction that decrements a 64-bit register and branches if
1140b57cec5SDimitry Andric   // the result is nonzero.
1150b57cec5SDimitry Andric   BranchCTG,
1160b57cec5SDimitry Andric 
1170b57cec5SDimitry Andric   // An instruction representing an asm goto statement.
1180b57cec5SDimitry Andric   AsmGoto
1190b57cec5SDimitry Andric };
1200b57cec5SDimitry Andric 
1210b57cec5SDimitry Andric // Information about a branch instruction.
1220b57cec5SDimitry Andric class Branch {
1230b57cec5SDimitry Andric   // The target of the branch. In case of INLINEASM_BR, this is nullptr.
1240b57cec5SDimitry Andric   const MachineOperand *Target;
1250b57cec5SDimitry Andric 
1260b57cec5SDimitry Andric public:
1270b57cec5SDimitry Andric   // The type of the branch.
1280b57cec5SDimitry Andric   BranchType Type;
1290b57cec5SDimitry Andric 
1300b57cec5SDimitry Andric   // CCMASK_<N> is set if CC might be equal to N.
1310b57cec5SDimitry Andric   unsigned CCValid;
1320b57cec5SDimitry Andric 
1330b57cec5SDimitry Andric   // CCMASK_<N> is set if the branch should be taken when CC == N.
1340b57cec5SDimitry Andric   unsigned CCMask;
1350b57cec5SDimitry Andric 
Branch(BranchType type,unsigned ccValid,unsigned ccMask,const MachineOperand * target)1360b57cec5SDimitry Andric   Branch(BranchType type, unsigned ccValid, unsigned ccMask,
1370b57cec5SDimitry Andric          const MachineOperand *target)
1380b57cec5SDimitry Andric     : Target(target), Type(type), CCValid(ccValid), CCMask(ccMask) {}
1390b57cec5SDimitry Andric 
isIndirect()1400b57cec5SDimitry Andric   bool isIndirect() { return Target != nullptr && Target->isReg(); }
hasMBBTarget()1410b57cec5SDimitry Andric   bool hasMBBTarget() { return Target != nullptr && Target->isMBB(); }
getMBBTarget()1420b57cec5SDimitry Andric   MachineBasicBlock *getMBBTarget() {
1430b57cec5SDimitry Andric     return hasMBBTarget() ? Target->getMBB() : nullptr;
1440b57cec5SDimitry Andric   }
1450b57cec5SDimitry Andric };
1460b57cec5SDimitry Andric 
1470b57cec5SDimitry Andric // Kinds of fused compares in compare-and-* instructions.  Together with type
1480b57cec5SDimitry Andric // of the converted compare, this identifies the compare-and-*
1490b57cec5SDimitry Andric // instruction.
1500b57cec5SDimitry Andric enum FusedCompareType {
1510b57cec5SDimitry Andric   // Relative branch - CRJ etc.
1520b57cec5SDimitry Andric   CompareAndBranch,
1530b57cec5SDimitry Andric 
1540b57cec5SDimitry Andric   // Indirect branch, used for return - CRBReturn etc.
1550b57cec5SDimitry Andric   CompareAndReturn,
1560b57cec5SDimitry Andric 
1570b57cec5SDimitry Andric   // Indirect branch, used for sibcall - CRBCall etc.
1580b57cec5SDimitry Andric   CompareAndSibcall,
1590b57cec5SDimitry Andric 
1600b57cec5SDimitry Andric   // Trap
1610b57cec5SDimitry Andric   CompareAndTrap
1620b57cec5SDimitry Andric };
1630b57cec5SDimitry Andric 
1640b57cec5SDimitry Andric } // end namespace SystemZII
1650b57cec5SDimitry Andric 
1660b57cec5SDimitry Andric namespace SystemZ {
1670b57cec5SDimitry Andric int getTwoOperandOpcode(uint16_t Opcode);
1680b57cec5SDimitry Andric int getTargetMemOpcode(uint16_t Opcode);
1695ffd83dbSDimitry Andric 
1705ffd83dbSDimitry Andric // Return a version of comparison CC mask CCMask in which the LT and GT
1715ffd83dbSDimitry Andric // actions are swapped.
1725ffd83dbSDimitry Andric unsigned reverseCCMask(unsigned CCMask);
1735ffd83dbSDimitry Andric 
1745ffd83dbSDimitry Andric // Create a new basic block after MBB.
1755ffd83dbSDimitry Andric MachineBasicBlock *emitBlockAfter(MachineBasicBlock *MBB);
1765ffd83dbSDimitry Andric // Split MBB after MI and return the new block (the one that contains
1775ffd83dbSDimitry Andric // instructions after MI).
1785ffd83dbSDimitry Andric MachineBasicBlock *splitBlockAfter(MachineBasicBlock::iterator MI,
1795ffd83dbSDimitry Andric                                    MachineBasicBlock *MBB);
1805ffd83dbSDimitry Andric // Split MBB before MI and return the new block (the one that contains MI).
1815ffd83dbSDimitry Andric MachineBasicBlock *splitBlockBefore(MachineBasicBlock::iterator MI,
1825ffd83dbSDimitry Andric                                     MachineBasicBlock *MBB);
1830b57cec5SDimitry Andric }
1840b57cec5SDimitry Andric 
1850b57cec5SDimitry Andric class SystemZInstrInfo : public SystemZGenInstrInfo {
1860b57cec5SDimitry Andric   const SystemZRegisterInfo RI;
1870b57cec5SDimitry Andric   SystemZSubtarget &STI;
1880b57cec5SDimitry Andric 
1890b57cec5SDimitry Andric   void splitMove(MachineBasicBlock::iterator MI, unsigned NewOpcode) const;
1900b57cec5SDimitry Andric   void splitAdjDynAlloc(MachineBasicBlock::iterator MI) const;
1910b57cec5SDimitry Andric   void expandRIPseudo(MachineInstr &MI, unsigned LowOpcode, unsigned HighOpcode,
1920b57cec5SDimitry Andric                       bool ConvertHigh) const;
1930b57cec5SDimitry Andric   void expandRIEPseudo(MachineInstr &MI, unsigned LowOpcode,
1940b57cec5SDimitry Andric                        unsigned LowOpcodeK, unsigned HighOpcode) const;
1950b57cec5SDimitry Andric   void expandRXYPseudo(MachineInstr &MI, unsigned LowOpcode,
1960b57cec5SDimitry Andric                        unsigned HighOpcode) const;
1970b57cec5SDimitry Andric   void expandLOCPseudo(MachineInstr &MI, unsigned LowOpcode,
1980b57cec5SDimitry Andric                        unsigned HighOpcode) const;
1990b57cec5SDimitry Andric   void expandZExtPseudo(MachineInstr &MI, unsigned LowOpcode,
2000b57cec5SDimitry Andric                         unsigned Size) const;
2010b57cec5SDimitry Andric   void expandLoadStackGuard(MachineInstr *MI) const;
2020b57cec5SDimitry Andric 
2030b57cec5SDimitry Andric   MachineInstrBuilder
2040b57cec5SDimitry Andric   emitGRX32Move(MachineBasicBlock &MBB, MachineBasicBlock::iterator MBBI,
2050b57cec5SDimitry Andric                 const DebugLoc &DL, unsigned DestReg, unsigned SrcReg,
2060b57cec5SDimitry Andric                 unsigned LowLowOpcode, unsigned Size, bool KillSrc,
2070b57cec5SDimitry Andric                 bool UndefSrc) const;
2080b57cec5SDimitry Andric 
2090b57cec5SDimitry Andric   virtual void anchor();
2100b57cec5SDimitry Andric 
2110b57cec5SDimitry Andric protected:
2120b57cec5SDimitry Andric   /// Commutes the operands in the given instruction by changing the operands
2130b57cec5SDimitry Andric   /// order and/or changing the instruction's opcode and/or the immediate value
2140b57cec5SDimitry Andric   /// operand.
2150b57cec5SDimitry Andric   ///
2160b57cec5SDimitry Andric   /// The arguments 'CommuteOpIdx1' and 'CommuteOpIdx2' specify the operands
2170b57cec5SDimitry Andric   /// to be commuted.
2180b57cec5SDimitry Andric   ///
2190b57cec5SDimitry Andric   /// Do not call this method for a non-commutable instruction or
2200b57cec5SDimitry Andric   /// non-commutable operands.
2210b57cec5SDimitry Andric   /// Even though the instruction is commutable, the method may still
2220b57cec5SDimitry Andric   /// fail to commute the operands, null pointer is returned in such cases.
2230b57cec5SDimitry Andric   MachineInstr *commuteInstructionImpl(MachineInstr &MI, bool NewMI,
2240b57cec5SDimitry Andric                                        unsigned CommuteOpIdx1,
2250b57cec5SDimitry Andric                                        unsigned CommuteOpIdx2) const override;
2260b57cec5SDimitry Andric 
2270b57cec5SDimitry Andric public:
2280b57cec5SDimitry Andric   explicit SystemZInstrInfo(SystemZSubtarget &STI);
2290b57cec5SDimitry Andric 
2300b57cec5SDimitry Andric   // Override TargetInstrInfo.
2310b57cec5SDimitry Andric   unsigned isLoadFromStackSlot(const MachineInstr &MI,
2320b57cec5SDimitry Andric                                int &FrameIndex) const override;
2330b57cec5SDimitry Andric   unsigned isStoreToStackSlot(const MachineInstr &MI,
2340b57cec5SDimitry Andric                               int &FrameIndex) const override;
2350b57cec5SDimitry Andric   bool isStackSlotCopy(const MachineInstr &MI, int &DestFrameIndex,
2360b57cec5SDimitry Andric                        int &SrcFrameIndex) const override;
2370b57cec5SDimitry Andric   bool analyzeBranch(MachineBasicBlock &MBB, MachineBasicBlock *&TBB,
2380b57cec5SDimitry Andric                      MachineBasicBlock *&FBB,
2390b57cec5SDimitry Andric                      SmallVectorImpl<MachineOperand> &Cond,
2400b57cec5SDimitry Andric                      bool AllowModify) const override;
2410b57cec5SDimitry Andric   unsigned removeBranch(MachineBasicBlock &MBB,
2420b57cec5SDimitry Andric                         int *BytesRemoved = nullptr) const override;
2430b57cec5SDimitry Andric   unsigned insertBranch(MachineBasicBlock &MBB, MachineBasicBlock *TBB,
2440b57cec5SDimitry Andric                         MachineBasicBlock *FBB, ArrayRef<MachineOperand> Cond,
2450b57cec5SDimitry Andric                         const DebugLoc &DL,
2460b57cec5SDimitry Andric                         int *BytesAdded = nullptr) const override;
2475ffd83dbSDimitry Andric   bool analyzeCompare(const MachineInstr &MI, Register &SrcReg,
248349cc55cSDimitry Andric                       Register &SrcReg2, int64_t &Mask,
249349cc55cSDimitry Andric                       int64_t &Value) const override;
2500b57cec5SDimitry Andric   bool canInsertSelect(const MachineBasicBlock &, ArrayRef<MachineOperand> Cond,
2515ffd83dbSDimitry Andric                        Register, Register, Register, int &, int &,
2525ffd83dbSDimitry Andric                        int &) const override;
2530b57cec5SDimitry Andric   void insertSelect(MachineBasicBlock &MBB, MachineBasicBlock::iterator MI,
2545ffd83dbSDimitry Andric                     const DebugLoc &DL, Register DstReg,
2555ffd83dbSDimitry Andric                     ArrayRef<MachineOperand> Cond, Register TrueReg,
2565ffd83dbSDimitry Andric                     Register FalseReg) const override;
2575ffd83dbSDimitry Andric   bool FoldImmediate(MachineInstr &UseMI, MachineInstr &DefMI, Register Reg,
2580b57cec5SDimitry Andric                      MachineRegisterInfo *MRI) const override;
2590b57cec5SDimitry Andric   bool isPredicable(const MachineInstr &MI) const override;
2600b57cec5SDimitry Andric   bool isProfitableToIfCvt(MachineBasicBlock &MBB, unsigned NumCycles,
2610b57cec5SDimitry Andric                            unsigned ExtraPredCycles,
2620b57cec5SDimitry Andric                            BranchProbability Probability) const override;
2630b57cec5SDimitry Andric   bool isProfitableToIfCvt(MachineBasicBlock &TMBB,
2640b57cec5SDimitry Andric                            unsigned NumCyclesT, unsigned ExtraPredCyclesT,
2650b57cec5SDimitry Andric                            MachineBasicBlock &FMBB,
2660b57cec5SDimitry Andric                            unsigned NumCyclesF, unsigned ExtraPredCyclesF,
2670b57cec5SDimitry Andric                            BranchProbability Probability) const override;
2680b57cec5SDimitry Andric   bool isProfitableToDupForIfCvt(MachineBasicBlock &MBB, unsigned NumCycles,
2690b57cec5SDimitry Andric                             BranchProbability Probability) const override;
2700b57cec5SDimitry Andric   bool PredicateInstruction(MachineInstr &MI,
2710b57cec5SDimitry Andric                             ArrayRef<MachineOperand> Pred) const override;
2720b57cec5SDimitry Andric   void copyPhysReg(MachineBasicBlock &MBB, MachineBasicBlock::iterator MBBI,
273480093f4SDimitry Andric                    const DebugLoc &DL, MCRegister DestReg, MCRegister SrcReg,
2740b57cec5SDimitry Andric                    bool KillSrc) const override;
2750b57cec5SDimitry Andric   void storeRegToStackSlot(MachineBasicBlock &MBB,
276bdd1243dSDimitry Andric                            MachineBasicBlock::iterator MBBI, Register SrcReg,
277bdd1243dSDimitry Andric                            bool isKill, int FrameIndex,
2780b57cec5SDimitry Andric                            const TargetRegisterClass *RC,
279bdd1243dSDimitry Andric                            const TargetRegisterInfo *TRI,
280bdd1243dSDimitry Andric                            Register VReg) const override;
2810b57cec5SDimitry Andric   void loadRegFromStackSlot(MachineBasicBlock &MBB,
282bdd1243dSDimitry Andric                             MachineBasicBlock::iterator MBBI, Register DestReg,
283bdd1243dSDimitry Andric                             int FrameIdx, const TargetRegisterClass *RC,
284bdd1243dSDimitry Andric                             const TargetRegisterInfo *TRI,
285bdd1243dSDimitry Andric                             Register VReg) const override;
286349cc55cSDimitry Andric   MachineInstr *convertToThreeAddress(MachineInstr &MI, LiveVariables *LV,
287349cc55cSDimitry Andric                                       LiveIntervals *LIS) const override;
2880b57cec5SDimitry Andric   MachineInstr *
2890b57cec5SDimitry Andric   foldMemoryOperandImpl(MachineFunction &MF, MachineInstr &MI,
2900b57cec5SDimitry Andric                         ArrayRef<unsigned> Ops,
2910b57cec5SDimitry Andric                         MachineBasicBlock::iterator InsertPt, int FrameIndex,
2920b57cec5SDimitry Andric                         LiveIntervals *LIS = nullptr,
2930b57cec5SDimitry Andric                         VirtRegMap *VRM = nullptr) const override;
2940b57cec5SDimitry Andric   MachineInstr *foldMemoryOperandImpl(
2950b57cec5SDimitry Andric       MachineFunction &MF, MachineInstr &MI, ArrayRef<unsigned> Ops,
2960b57cec5SDimitry Andric       MachineBasicBlock::iterator InsertPt, MachineInstr &LoadMI,
2970b57cec5SDimitry Andric       LiveIntervals *LIS = nullptr) const override;
2980b57cec5SDimitry Andric   bool expandPostRAPseudo(MachineInstr &MBBI) const override;
2990b57cec5SDimitry Andric   bool reverseBranchCondition(SmallVectorImpl<MachineOperand> &Cond) const
3000b57cec5SDimitry Andric     override;
3010b57cec5SDimitry Andric 
3020b57cec5SDimitry Andric   // Return the SystemZRegisterInfo, which this class owns.
getRegisterInfo()3030b57cec5SDimitry Andric   const SystemZRegisterInfo &getRegisterInfo() const { return RI; }
3040b57cec5SDimitry Andric 
3050b57cec5SDimitry Andric   // Return the size in bytes of MI.
3060b57cec5SDimitry Andric   unsigned getInstSizeInBytes(const MachineInstr &MI) const override;
3070b57cec5SDimitry Andric 
3080b57cec5SDimitry Andric   // Return true if MI is a conditional or unconditional branch.
3090b57cec5SDimitry Andric   // When returning true, set Cond to the mask of condition-code
3100b57cec5SDimitry Andric   // values on which the instruction will branch, and set Target
3110b57cec5SDimitry Andric   // to the operand that contains the branch target.  This target
3120b57cec5SDimitry Andric   // can be a register or a basic block.
3130b57cec5SDimitry Andric   SystemZII::Branch getBranchInfo(const MachineInstr &MI) const;
3140b57cec5SDimitry Andric 
3150b57cec5SDimitry Andric   // Get the load and store opcodes for a given register class.
3160b57cec5SDimitry Andric   void getLoadStoreOpcodes(const TargetRegisterClass *RC,
3170b57cec5SDimitry Andric                            unsigned &LoadOpcode, unsigned &StoreOpcode) const;
3180b57cec5SDimitry Andric 
3190b57cec5SDimitry Andric   // Opcode is the opcode of an instruction that has an address operand,
3200b57cec5SDimitry Andric   // and the caller wants to perform that instruction's operation on an
3210b57cec5SDimitry Andric   // address that has displacement Offset.  Return the opcode of a suitable
3220b57cec5SDimitry Andric   // instruction (which might be Opcode itself) or 0 if no such instruction
32381ad6265SDimitry Andric   // exists.  MI may be passed in order to allow examination of physical
32481ad6265SDimitry Andric   // register operands (i.e. if a VR32/64 reg ended up as an FP or Vector reg).
32581ad6265SDimitry Andric   unsigned getOpcodeForOffset(unsigned Opcode, int64_t Offset,
32681ad6265SDimitry Andric                               const MachineInstr *MI = nullptr) const;
3270b57cec5SDimitry Andric 
3281fd87a68SDimitry Andric   // Return true if Opcode has a mapping in 12 <-> 20 bit displacements.
3291fd87a68SDimitry Andric   bool hasDisplacementPairInsn(unsigned Opcode) const;
3301fd87a68SDimitry Andric 
3310b57cec5SDimitry Andric   // If Opcode is a load instruction that has a LOAD AND TEST form,
3320b57cec5SDimitry Andric   // return the opcode for the testing form, otherwise return 0.
3330b57cec5SDimitry Andric   unsigned getLoadAndTest(unsigned Opcode) const;
3340b57cec5SDimitry Andric 
3350b57cec5SDimitry Andric   // Return true if ROTATE AND ... SELECTED BITS can be used to select bits
3360b57cec5SDimitry Andric   // Mask of the R2 operand, given that only the low BitSize bits of Mask are
3370b57cec5SDimitry Andric   // significant.  Set Start and End to the I3 and I4 operands if so.
3380b57cec5SDimitry Andric   bool isRxSBGMask(uint64_t Mask, unsigned BitSize,
3390b57cec5SDimitry Andric                    unsigned &Start, unsigned &End) const;
3400b57cec5SDimitry Andric 
3410b57cec5SDimitry Andric   // If Opcode is a COMPARE opcode for which an associated fused COMPARE AND *
3420b57cec5SDimitry Andric   // operation exists, return the opcode for the latter, otherwise return 0.
3430b57cec5SDimitry Andric   // MI, if nonnull, is the compare instruction.
3440b57cec5SDimitry Andric   unsigned getFusedCompare(unsigned Opcode,
3450b57cec5SDimitry Andric                            SystemZII::FusedCompareType Type,
3460b57cec5SDimitry Andric                            const MachineInstr *MI = nullptr) const;
3470b57cec5SDimitry Andric 
3485ffd83dbSDimitry Andric   // Try to find all CC users of the compare instruction (MBBI) and update
3495ffd83dbSDimitry Andric   // all of them to maintain equivalent behavior after swapping the compare
3505ffd83dbSDimitry Andric   // operands. Return false if not all users can be conclusively found and
3515ffd83dbSDimitry Andric   // handled. The compare instruction is *not* changed.
3525ffd83dbSDimitry Andric   bool prepareCompareSwapOperands(MachineBasicBlock::iterator MBBI) const;
3535ffd83dbSDimitry Andric 
3540b57cec5SDimitry Andric   // If Opcode is a LOAD opcode for with an associated LOAD AND TRAP
3550b57cec5SDimitry Andric   // operation exists, returh the opcode for the latter, otherwise return 0.
3560b57cec5SDimitry Andric   unsigned getLoadAndTrap(unsigned Opcode) const;
3570b57cec5SDimitry Andric 
3580b57cec5SDimitry Andric   // Emit code before MBBI in MI to move immediate value Value into
3590b57cec5SDimitry Andric   // physical register Reg.
3600b57cec5SDimitry Andric   void loadImmediate(MachineBasicBlock &MBB,
3610b57cec5SDimitry Andric                      MachineBasicBlock::iterator MBBI,
3620b57cec5SDimitry Andric                      unsigned Reg, uint64_t Value) const;
3630b57cec5SDimitry Andric 
364480093f4SDimitry Andric   // Perform target specific instruction verification.
365480093f4SDimitry Andric   bool verifyInstruction(const MachineInstr &MI,
366480093f4SDimitry Andric                          StringRef &ErrInfo) const override;
367480093f4SDimitry Andric 
3680b57cec5SDimitry Andric   // Sometimes, it is possible for the target to tell, even without
3690b57cec5SDimitry Andric   // aliasing information, that two MIs access different memory
3700b57cec5SDimitry Andric   // addresses. This function returns true if two MIs access different
3710b57cec5SDimitry Andric   // memory addresses and false otherwise.
3720b57cec5SDimitry Andric   bool
3730b57cec5SDimitry Andric   areMemAccessesTriviallyDisjoint(const MachineInstr &MIa,
3748bcb0991SDimitry Andric                                   const MachineInstr &MIb) const override;
3750b57cec5SDimitry Andric };
3760b57cec5SDimitry Andric 
3770b57cec5SDimitry Andric } // end namespace llvm
3780b57cec5SDimitry Andric 
3790b57cec5SDimitry Andric #endif // LLVM_LIB_TARGET_SYSTEMZ_SYSTEMZINSTRINFO_H
380