1251607Sdim//===-- SystemZInstrInfo.h - SystemZ instruction information ----*- C++ -*-===// 2251607Sdim// 3353358Sdim// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 4353358Sdim// See https://llvm.org/LICENSE.txt for license information. 5353358Sdim// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 6251607Sdim// 7251607Sdim//===----------------------------------------------------------------------===// 8251607Sdim// 9251607Sdim// This file contains the SystemZ implementation of the TargetInstrInfo class. 10251607Sdim// 11251607Sdim//===----------------------------------------------------------------------===// 12251607Sdim 13280031Sdim#ifndef LLVM_LIB_TARGET_SYSTEMZ_SYSTEMZINSTRINFO_H 14280031Sdim#define LLVM_LIB_TARGET_SYSTEMZ_SYSTEMZINSTRINFO_H 15251607Sdim 16251607Sdim#include "SystemZ.h" 17251607Sdim#include "SystemZRegisterInfo.h" 18321369Sdim#include "llvm/ADT/ArrayRef.h" 19321369Sdim#include "llvm/CodeGen/MachineBasicBlock.h" 20321369Sdim#include "llvm/CodeGen/MachineFunction.h" 21321369Sdim#include "llvm/CodeGen/MachineInstrBuilder.h" 22327952Sdim#include "llvm/CodeGen/TargetInstrInfo.h" 23321369Sdim#include <cstdint> 24251607Sdim 25251607Sdim#define GET_INSTRINFO_HEADER 26251607Sdim#include "SystemZGenInstrInfo.inc" 27251607Sdim 28251607Sdimnamespace llvm { 29251607Sdim 30321369Sdimclass SystemZSubtarget; 31251607Sdim 32251607Sdimnamespace SystemZII { 33321369Sdim 34276479Sdimenum { 35276479Sdim // See comments in SystemZInstrFormats.td. 36276479Sdim SimpleBDXLoad = (1 << 0), 37276479Sdim SimpleBDXStore = (1 << 1), 38276479Sdim Has20BitOffset = (1 << 2), 39276479Sdim HasIndex = (1 << 3), 40276479Sdim Is128Bit = (1 << 4), 41276479Sdim AccessSizeMask = (31 << 5), 42276479Sdim AccessSizeShift = 5, 43276479Sdim CCValuesMask = (15 << 10), 44276479Sdim CCValuesShift = 10, 45276479Sdim CompareZeroCCMaskMask = (15 << 14), 46276479Sdim CompareZeroCCMaskShift = 14, 47276479Sdim CCMaskFirst = (1 << 18), 48276479Sdim CCMaskLast = (1 << 19), 49360784Sdim IsLogical = (1 << 20), 50360784Sdim CCIfNoSignedWrap = (1 << 21) 51276479Sdim}; 52321369Sdim 53276479Sdimstatic inline unsigned getAccessSize(unsigned int Flags) { 54276479Sdim return (Flags & AccessSizeMask) >> AccessSizeShift; 55276479Sdim} 56321369Sdim 57276479Sdimstatic inline unsigned getCCValues(unsigned int Flags) { 58276479Sdim return (Flags & CCValuesMask) >> CCValuesShift; 59276479Sdim} 60321369Sdim 61276479Sdimstatic inline unsigned getCompareZeroCCMask(unsigned int Flags) { 62276479Sdim return (Flags & CompareZeroCCMaskMask) >> CompareZeroCCMaskShift; 63276479Sdim} 64261991Sdim 65276479Sdim// SystemZ MachineOperand target flags. 66276479Sdimenum { 67276479Sdim // Masks out the bits for the access model. 68288943Sdim MO_SYMBOL_MODIFIER = (3 << 0), 69251607Sdim 70276479Sdim // @GOT (aka @GOTENT) 71288943Sdim MO_GOT = (1 << 0), 72288943Sdim 73288943Sdim // @INDNTPOFF 74288943Sdim MO_INDNTPOFF = (2 << 0) 75276479Sdim}; 76321369Sdim 77276479Sdim// Classifies a branch. 78276479Sdimenum BranchType { 79276479Sdim // An instruction that branches on the current value of CC. 80276479Sdim BranchNormal, 81261991Sdim 82276479Sdim // An instruction that peforms a 32-bit signed comparison and branches 83276479Sdim // on the result. 84276479Sdim BranchC, 85261991Sdim 86276479Sdim // An instruction that peforms a 32-bit unsigned comparison and branches 87276479Sdim // on the result. 88276479Sdim BranchCL, 89261991Sdim 90276479Sdim // An instruction that peforms a 64-bit signed comparison and branches 91276479Sdim // on the result. 92276479Sdim BranchCG, 93261991Sdim 94276479Sdim // An instruction that peforms a 64-bit unsigned comparison and branches 95276479Sdim // on the result. 96276479Sdim BranchCLG, 97261991Sdim 98276479Sdim // An instruction that decrements a 32-bit register and branches if 99276479Sdim // the result is nonzero. 100276479Sdim BranchCT, 101261991Sdim 102276479Sdim // An instruction that decrements a 64-bit register and branches if 103276479Sdim // the result is nonzero. 104353358Sdim BranchCTG, 105353358Sdim 106353358Sdim // An instruction representing an asm goto statement. 107353358Sdim AsmGoto 108276479Sdim}; 109321369Sdim 110276479Sdim// Information about a branch instruction. 111353358Sdimclass Branch { 112353358Sdim // The target of the branch. In case of INLINEASM_BR, this is nullptr. 113353358Sdim const MachineOperand *Target; 114353358Sdim 115353358Sdimpublic: 116276479Sdim // The type of the branch. 117276479Sdim BranchType Type; 118261991Sdim 119276479Sdim // CCMASK_<N> is set if CC might be equal to N. 120276479Sdim unsigned CCValid; 121261991Sdim 122276479Sdim // CCMASK_<N> is set if the branch should be taken when CC == N. 123276479Sdim unsigned CCMask; 124261991Sdim 125276479Sdim Branch(BranchType type, unsigned ccValid, unsigned ccMask, 126276479Sdim const MachineOperand *target) 127353358Sdim : Target(target), Type(type), CCValid(ccValid), CCMask(ccMask) {} 128353358Sdim 129353358Sdim bool isIndirect() { return Target != nullptr && Target->isReg(); } 130353358Sdim bool hasMBBTarget() { return Target != nullptr && Target->isMBB(); } 131353358Sdim MachineBasicBlock *getMBBTarget() { 132353358Sdim return hasMBBTarget() ? Target->getMBB() : nullptr; 133353358Sdim } 134276479Sdim}; 135321369Sdim 136309124Sdim// Kinds of fused compares in compare-and-* instructions. Together with type 137309124Sdim// of the converted compare, this identifies the compare-and-* 138309124Sdim// instruction. 139309124Sdimenum FusedCompareType { 140309124Sdim // Relative branch - CRJ etc. 141309124Sdim CompareAndBranch, 142309124Sdim 143309124Sdim // Indirect branch, used for return - CRBReturn etc. 144309124Sdim CompareAndReturn, 145309124Sdim 146309124Sdim // Indirect branch, used for sibcall - CRBCall etc. 147309124Sdim CompareAndSibcall, 148309124Sdim 149309124Sdim // Trap 150309124Sdim CompareAndTrap 151309124Sdim}; 152321369Sdim 153276479Sdim} // end namespace SystemZII 154251607Sdim 155353358Sdimnamespace SystemZ { 156353358Sdimint getTwoOperandOpcode(uint16_t Opcode); 157353358Sdimint getTargetMemOpcode(uint16_t Opcode); 158353358Sdim} 159353358Sdim 160251607Sdimclass SystemZInstrInfo : public SystemZGenInstrInfo { 161251607Sdim const SystemZRegisterInfo RI; 162276479Sdim SystemZSubtarget &STI; 163251607Sdim 164251607Sdim void splitMove(MachineBasicBlock::iterator MI, unsigned NewOpcode) const; 165251607Sdim void splitAdjDynAlloc(MachineBasicBlock::iterator MI) const; 166309124Sdim void expandRIPseudo(MachineInstr &MI, unsigned LowOpcode, unsigned HighOpcode, 167309124Sdim bool ConvertHigh) const; 168309124Sdim void expandRIEPseudo(MachineInstr &MI, unsigned LowOpcode, 169261991Sdim unsigned LowOpcodeK, unsigned HighOpcode) const; 170309124Sdim void expandRXYPseudo(MachineInstr &MI, unsigned LowOpcode, 171261991Sdim unsigned HighOpcode) const; 172314564Sdim void expandLOCPseudo(MachineInstr &MI, unsigned LowOpcode, 173314564Sdim unsigned HighOpcode) const; 174309124Sdim void expandZExtPseudo(MachineInstr &MI, unsigned LowOpcode, 175261991Sdim unsigned Size) const; 176309124Sdim void expandLoadStackGuard(MachineInstr *MI) const; 177321369Sdim 178321369Sdim MachineInstrBuilder 179321369Sdim emitGRX32Move(MachineBasicBlock &MBB, MachineBasicBlock::iterator MBBI, 180321369Sdim const DebugLoc &DL, unsigned DestReg, unsigned SrcReg, 181321369Sdim unsigned LowLowOpcode, unsigned Size, bool KillSrc, 182321369Sdim bool UndefSrc) const; 183321369Sdim 184261991Sdim virtual void anchor(); 185314564Sdim 186314564Sdimprotected: 187314564Sdim /// Commutes the operands in the given instruction by changing the operands 188314564Sdim /// order and/or changing the instruction's opcode and/or the immediate value 189314564Sdim /// operand. 190314564Sdim /// 191314564Sdim /// The arguments 'CommuteOpIdx1' and 'CommuteOpIdx2' specify the operands 192314564Sdim /// to be commuted. 193314564Sdim /// 194314564Sdim /// Do not call this method for a non-commutable instruction or 195314564Sdim /// non-commutable operands. 196314564Sdim /// Even though the instruction is commutable, the method may still 197314564Sdim /// fail to commute the operands, null pointer is returned in such cases. 198314564Sdim MachineInstr *commuteInstructionImpl(MachineInstr &MI, bool NewMI, 199314564Sdim unsigned CommuteOpIdx1, 200314564Sdim unsigned CommuteOpIdx2) const override; 201314564Sdim 202251607Sdimpublic: 203276479Sdim explicit SystemZInstrInfo(SystemZSubtarget &STI); 204251607Sdim 205251607Sdim // Override TargetInstrInfo. 206309124Sdim unsigned isLoadFromStackSlot(const MachineInstr &MI, 207276479Sdim int &FrameIndex) const override; 208309124Sdim unsigned isStoreToStackSlot(const MachineInstr &MI, 209276479Sdim int &FrameIndex) const override; 210309124Sdim bool isStackSlotCopy(const MachineInstr &MI, int &DestFrameIndex, 211276479Sdim int &SrcFrameIndex) const override; 212309124Sdim bool analyzeBranch(MachineBasicBlock &MBB, MachineBasicBlock *&TBB, 213276479Sdim MachineBasicBlock *&FBB, 214276479Sdim SmallVectorImpl<MachineOperand> &Cond, 215276479Sdim bool AllowModify) const override; 216314564Sdim unsigned removeBranch(MachineBasicBlock &MBB, 217314564Sdim int *BytesRemoved = nullptr) const override; 218314564Sdim unsigned insertBranch(MachineBasicBlock &MBB, MachineBasicBlock *TBB, 219288943Sdim MachineBasicBlock *FBB, ArrayRef<MachineOperand> Cond, 220314564Sdim const DebugLoc &DL, 221314564Sdim int *BytesAdded = nullptr) const override; 222309124Sdim bool analyzeCompare(const MachineInstr &MI, unsigned &SrcReg, 223276479Sdim unsigned &SrcReg2, int &Mask, int &Value) const override; 224314564Sdim bool canInsertSelect(const MachineBasicBlock&, ArrayRef<MachineOperand> Cond, 225314564Sdim unsigned, unsigned, int&, int&, int&) const override; 226314564Sdim void insertSelect(MachineBasicBlock &MBB, MachineBasicBlock::iterator MI, 227314564Sdim const DebugLoc &DL, unsigned DstReg, 228314564Sdim ArrayRef<MachineOperand> Cond, unsigned TrueReg, 229314564Sdim unsigned FalseReg) const override; 230314564Sdim bool FoldImmediate(MachineInstr &UseMI, MachineInstr &DefMI, unsigned Reg, 231314564Sdim MachineRegisterInfo *MRI) const override; 232321369Sdim bool isPredicable(const MachineInstr &MI) const override; 233276479Sdim bool isProfitableToIfCvt(MachineBasicBlock &MBB, unsigned NumCycles, 234276479Sdim unsigned ExtraPredCycles, 235296417Sdim BranchProbability Probability) const override; 236276479Sdim bool isProfitableToIfCvt(MachineBasicBlock &TMBB, 237276479Sdim unsigned NumCyclesT, unsigned ExtraPredCyclesT, 238276479Sdim MachineBasicBlock &FMBB, 239276479Sdim unsigned NumCyclesF, unsigned ExtraPredCyclesF, 240296417Sdim BranchProbability Probability) const override; 241309124Sdim bool isProfitableToDupForIfCvt(MachineBasicBlock &MBB, unsigned NumCycles, 242309124Sdim BranchProbability Probability) const override; 243309124Sdim bool PredicateInstruction(MachineInstr &MI, 244288943Sdim ArrayRef<MachineOperand> Pred) const override; 245276479Sdim void copyPhysReg(MachineBasicBlock &MBB, MachineBasicBlock::iterator MBBI, 246360784Sdim const DebugLoc &DL, MCRegister DestReg, MCRegister SrcReg, 247276479Sdim bool KillSrc) const override; 248276479Sdim void storeRegToStackSlot(MachineBasicBlock &MBB, 249276479Sdim MachineBasicBlock::iterator MBBI, 250276479Sdim unsigned SrcReg, bool isKill, int FrameIndex, 251276479Sdim const TargetRegisterClass *RC, 252276479Sdim const TargetRegisterInfo *TRI) const override; 253276479Sdim void loadRegFromStackSlot(MachineBasicBlock &MBB, 254276479Sdim MachineBasicBlock::iterator MBBI, 255276479Sdim unsigned DestReg, int FrameIdx, 256276479Sdim const TargetRegisterClass *RC, 257276479Sdim const TargetRegisterInfo *TRI) const override; 258276479Sdim MachineInstr *convertToThreeAddress(MachineFunction::iterator &MFI, 259309124Sdim MachineInstr &MI, 260276479Sdim LiveVariables *LV) const override; 261309124Sdim MachineInstr * 262309124Sdim foldMemoryOperandImpl(MachineFunction &MF, MachineInstr &MI, 263309124Sdim ArrayRef<unsigned> Ops, 264309124Sdim MachineBasicBlock::iterator InsertPt, int FrameIndex, 265353358Sdim LiveIntervals *LIS = nullptr, 266353358Sdim VirtRegMap *VRM = nullptr) const override; 267309124Sdim MachineInstr *foldMemoryOperandImpl( 268309124Sdim MachineFunction &MF, MachineInstr &MI, ArrayRef<unsigned> Ops, 269309124Sdim MachineBasicBlock::iterator InsertPt, MachineInstr &LoadMI, 270309124Sdim LiveIntervals *LIS = nullptr) const override; 271309124Sdim bool expandPostRAPseudo(MachineInstr &MBBI) const override; 272314564Sdim bool reverseBranchCondition(SmallVectorImpl<MachineOperand> &Cond) const 273276479Sdim override; 274251607Sdim 275251607Sdim // Return the SystemZRegisterInfo, which this class owns. 276251607Sdim const SystemZRegisterInfo &getRegisterInfo() const { return RI; } 277251607Sdim 278261991Sdim // Return the size in bytes of MI. 279314564Sdim unsigned getInstSizeInBytes(const MachineInstr &MI) const override; 280261991Sdim 281251607Sdim // Return true if MI is a conditional or unconditional branch. 282251607Sdim // When returning true, set Cond to the mask of condition-code 283251607Sdim // values on which the instruction will branch, and set Target 284251607Sdim // to the operand that contains the branch target. This target 285251607Sdim // can be a register or a basic block. 286309124Sdim SystemZII::Branch getBranchInfo(const MachineInstr &MI) const; 287251607Sdim 288251607Sdim // Get the load and store opcodes for a given register class. 289251607Sdim void getLoadStoreOpcodes(const TargetRegisterClass *RC, 290251607Sdim unsigned &LoadOpcode, unsigned &StoreOpcode) const; 291251607Sdim 292251607Sdim // Opcode is the opcode of an instruction that has an address operand, 293251607Sdim // and the caller wants to perform that instruction's operation on an 294251607Sdim // address that has displacement Offset. Return the opcode of a suitable 295251607Sdim // instruction (which might be Opcode itself) or 0 if no such instruction 296251607Sdim // exists. 297251607Sdim unsigned getOpcodeForOffset(unsigned Opcode, int64_t Offset) const; 298251607Sdim 299261991Sdim // If Opcode is a load instruction that has a LOAD AND TEST form, 300261991Sdim // return the opcode for the testing form, otherwise return 0. 301261991Sdim unsigned getLoadAndTest(unsigned Opcode) const; 302261991Sdim 303261991Sdim // Return true if ROTATE AND ... SELECTED BITS can be used to select bits 304261991Sdim // Mask of the R2 operand, given that only the low BitSize bits of Mask are 305261991Sdim // significant. Set Start and End to the I3 and I4 operands if so. 306261991Sdim bool isRxSBGMask(uint64_t Mask, unsigned BitSize, 307261991Sdim unsigned &Start, unsigned &End) const; 308261991Sdim 309309124Sdim // If Opcode is a COMPARE opcode for which an associated fused COMPARE AND * 310309124Sdim // operation exists, return the opcode for the latter, otherwise return 0. 311261991Sdim // MI, if nonnull, is the compare instruction. 312309124Sdim unsigned getFusedCompare(unsigned Opcode, 313309124Sdim SystemZII::FusedCompareType Type, 314309124Sdim const MachineInstr *MI = nullptr) const; 315261991Sdim 316314564Sdim // If Opcode is a LOAD opcode for with an associated LOAD AND TRAP 317314564Sdim // operation exists, returh the opcode for the latter, otherwise return 0. 318314564Sdim unsigned getLoadAndTrap(unsigned Opcode) const; 319314564Sdim 320251607Sdim // Emit code before MBBI in MI to move immediate value Value into 321251607Sdim // physical register Reg. 322251607Sdim void loadImmediate(MachineBasicBlock &MBB, 323251607Sdim MachineBasicBlock::iterator MBBI, 324251607Sdim unsigned Reg, uint64_t Value) const; 325314564Sdim 326360784Sdim // Perform target specific instruction verification. 327360784Sdim bool verifyInstruction(const MachineInstr &MI, 328360784Sdim StringRef &ErrInfo) const override; 329360784Sdim 330314564Sdim // Sometimes, it is possible for the target to tell, even without 331314564Sdim // aliasing information, that two MIs access different memory 332314564Sdim // addresses. This function returns true if two MIs access different 333314564Sdim // memory addresses and false otherwise. 334314564Sdim bool 335353358Sdim areMemAccessesTriviallyDisjoint(const MachineInstr &MIa, 336360784Sdim const MachineInstr &MIb) const override; 337251607Sdim}; 338321369Sdim 339251607Sdim} // end namespace llvm 340251607Sdim 341321369Sdim#endif // LLVM_LIB_TARGET_SYSTEMZ_SYSTEMZINSTRINFO_H 342