Path: blob/main/contrib/llvm-project/llvm/lib/Target/SystemZ/SystemZInstrInfo.h
35269 views
//===-- SystemZInstrInfo.h - SystemZ instruction information ----*- C++ -*-===//1//2// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.3// See https://llvm.org/LICENSE.txt for license information.4// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception5//6//===----------------------------------------------------------------------===//7//8// This file contains the SystemZ implementation of the TargetInstrInfo class.9//10//===----------------------------------------------------------------------===//1112#ifndef LLVM_LIB_TARGET_SYSTEMZ_SYSTEMZINSTRINFO_H13#define LLVM_LIB_TARGET_SYSTEMZ_SYSTEMZINSTRINFO_H1415#include "SystemZ.h"16#include "SystemZRegisterInfo.h"17#include "llvm/ADT/ArrayRef.h"18#include "llvm/CodeGen/MachineBasicBlock.h"19#include "llvm/CodeGen/MachineFunction.h"20#include "llvm/CodeGen/MachineInstrBuilder.h"21#include "llvm/CodeGen/TargetInstrInfo.h"22#include <cstdint>2324#define GET_INSTRINFO_HEADER25#include "SystemZGenInstrInfo.inc"2627namespace llvm {2829class SystemZSubtarget;3031namespace SystemZII {3233enum {34// See comments in SystemZInstrFormats.td.35SimpleBDXLoad = (1 << 0),36SimpleBDXStore = (1 << 1),37Has20BitOffset = (1 << 2),38HasIndex = (1 << 3),39Is128Bit = (1 << 4),40AccessSizeMask = (31 << 5),41AccessSizeShift = 5,42CCValuesMask = (15 << 10),43CCValuesShift = 10,44CompareZeroCCMaskMask = (15 << 14),45CompareZeroCCMaskShift = 14,46CCMaskFirst = (1 << 18),47CCMaskLast = (1 << 19),48IsLogical = (1 << 20),49CCIfNoSignedWrap = (1 << 21)50};5152static inline unsigned getAccessSize(unsigned int Flags) {53return (Flags & AccessSizeMask) >> AccessSizeShift;54}5556static inline unsigned getCCValues(unsigned int Flags) {57return (Flags & CCValuesMask) >> CCValuesShift;58}5960static inline unsigned getCompareZeroCCMask(unsigned int Flags) {61return (Flags & CompareZeroCCMaskMask) >> CompareZeroCCMaskShift;62}6364// SystemZ MachineOperand target flags.65enum {66// Masks out the bits for the access model.67MO_SYMBOL_MODIFIER = (3 << 0),6869// @GOT (aka @GOTENT)70MO_GOT = (1 << 0),7172// @INDNTPOFF73MO_INDNTPOFF = (2 << 0)74};7576// z/OS XPLink specific: classifies the types of77// accesses to the ADA (Associated Data Area).78// These enums contains values that overlap with the above MO_ enums,79// but that's fine since the above enums are used with ELF,80// while these values are used with z/OS.81enum {82MO_ADA_DATA_SYMBOL_ADDR = 1,83MO_ADA_INDIRECT_FUNC_DESC,84MO_ADA_DIRECT_FUNC_DESC,85};8687// Classifies a branch.88enum BranchType {89// An instruction that branches on the current value of CC.90BranchNormal,9192// An instruction that peforms a 32-bit signed comparison and branches93// on the result.94BranchC,9596// An instruction that peforms a 32-bit unsigned comparison and branches97// on the result.98BranchCL,99100// An instruction that peforms a 64-bit signed comparison and branches101// on the result.102BranchCG,103104// An instruction that peforms a 64-bit unsigned comparison and branches105// on the result.106BranchCLG,107108// An instruction that decrements a 32-bit register and branches if109// the result is nonzero.110BranchCT,111112// An instruction that decrements a 64-bit register and branches if113// the result is nonzero.114BranchCTG,115116// An instruction representing an asm goto statement.117AsmGoto118};119120// Information about a branch instruction.121class Branch {122// The target of the branch. In case of INLINEASM_BR, this is nullptr.123const MachineOperand *Target;124125public:126// The type of the branch.127BranchType Type;128129// CCMASK_<N> is set if CC might be equal to N.130unsigned CCValid;131132// CCMASK_<N> is set if the branch should be taken when CC == N.133unsigned CCMask;134135Branch(BranchType type, unsigned ccValid, unsigned ccMask,136const MachineOperand *target)137: Target(target), Type(type), CCValid(ccValid), CCMask(ccMask) {}138139bool isIndirect() { return Target != nullptr && Target->isReg(); }140bool hasMBBTarget() { return Target != nullptr && Target->isMBB(); }141MachineBasicBlock *getMBBTarget() {142return hasMBBTarget() ? Target->getMBB() : nullptr;143}144};145146// Kinds of fused compares in compare-and-* instructions. Together with type147// of the converted compare, this identifies the compare-and-*148// instruction.149enum FusedCompareType {150// Relative branch - CRJ etc.151CompareAndBranch,152153// Indirect branch, used for return - CRBReturn etc.154CompareAndReturn,155156// Indirect branch, used for sibcall - CRBCall etc.157CompareAndSibcall,158159// Trap160CompareAndTrap161};162163} // end namespace SystemZII164165namespace SystemZ {166int getTwoOperandOpcode(uint16_t Opcode);167int getTargetMemOpcode(uint16_t Opcode);168169// Return a version of comparison CC mask CCMask in which the LT and GT170// actions are swapped.171unsigned reverseCCMask(unsigned CCMask);172173// Create a new basic block after MBB.174MachineBasicBlock *emitBlockAfter(MachineBasicBlock *MBB);175// Split MBB after MI and return the new block (the one that contains176// instructions after MI).177MachineBasicBlock *splitBlockAfter(MachineBasicBlock::iterator MI,178MachineBasicBlock *MBB);179// Split MBB before MI and return the new block (the one that contains MI).180MachineBasicBlock *splitBlockBefore(MachineBasicBlock::iterator MI,181MachineBasicBlock *MBB);182}183184class SystemZInstrInfo : public SystemZGenInstrInfo {185const SystemZRegisterInfo RI;186SystemZSubtarget &STI;187188void splitMove(MachineBasicBlock::iterator MI, unsigned NewOpcode) const;189void splitAdjDynAlloc(MachineBasicBlock::iterator MI) const;190void expandRIPseudo(MachineInstr &MI, unsigned LowOpcode, unsigned HighOpcode,191bool ConvertHigh) const;192void expandRIEPseudo(MachineInstr &MI, unsigned LowOpcode,193unsigned LowOpcodeK, unsigned HighOpcode) const;194void expandRXYPseudo(MachineInstr &MI, unsigned LowOpcode,195unsigned HighOpcode) const;196void expandLOCPseudo(MachineInstr &MI, unsigned LowOpcode,197unsigned HighOpcode) const;198void expandZExtPseudo(MachineInstr &MI, unsigned LowOpcode,199unsigned Size) const;200void expandLoadStackGuard(MachineInstr *MI) const;201202MachineInstrBuilder203emitGRX32Move(MachineBasicBlock &MBB, MachineBasicBlock::iterator MBBI,204const DebugLoc &DL, unsigned DestReg, unsigned SrcReg,205unsigned LowLowOpcode, unsigned Size, bool KillSrc,206bool UndefSrc) const;207208virtual void anchor();209210protected:211/// Commutes the operands in the given instruction by changing the operands212/// order and/or changing the instruction's opcode and/or the immediate value213/// operand.214///215/// The arguments 'CommuteOpIdx1' and 'CommuteOpIdx2' specify the operands216/// to be commuted.217///218/// Do not call this method for a non-commutable instruction or219/// non-commutable operands.220/// Even though the instruction is commutable, the method may still221/// fail to commute the operands, null pointer is returned in such cases.222MachineInstr *commuteInstructionImpl(MachineInstr &MI, bool NewMI,223unsigned CommuteOpIdx1,224unsigned CommuteOpIdx2) const override;225226public:227explicit SystemZInstrInfo(SystemZSubtarget &STI);228229// Override TargetInstrInfo.230Register isLoadFromStackSlot(const MachineInstr &MI,231int &FrameIndex) const override;232Register isStoreToStackSlot(const MachineInstr &MI,233int &FrameIndex) const override;234bool isStackSlotCopy(const MachineInstr &MI, int &DestFrameIndex,235int &SrcFrameIndex) const override;236bool analyzeBranch(MachineBasicBlock &MBB, MachineBasicBlock *&TBB,237MachineBasicBlock *&FBB,238SmallVectorImpl<MachineOperand> &Cond,239bool AllowModify) const override;240unsigned removeBranch(MachineBasicBlock &MBB,241int *BytesRemoved = nullptr) const override;242unsigned insertBranch(MachineBasicBlock &MBB, MachineBasicBlock *TBB,243MachineBasicBlock *FBB, ArrayRef<MachineOperand> Cond,244const DebugLoc &DL,245int *BytesAdded = nullptr) const override;246bool analyzeCompare(const MachineInstr &MI, Register &SrcReg,247Register &SrcReg2, int64_t &Mask,248int64_t &Value) const override;249bool canInsertSelect(const MachineBasicBlock &, ArrayRef<MachineOperand> Cond,250Register, Register, Register, int &, int &,251int &) const override;252void insertSelect(MachineBasicBlock &MBB, MachineBasicBlock::iterator MI,253const DebugLoc &DL, Register DstReg,254ArrayRef<MachineOperand> Cond, Register TrueReg,255Register FalseReg) const override;256MachineInstr *optimizeLoadInstr(MachineInstr &MI,257const MachineRegisterInfo *MRI,258Register &FoldAsLoadDefReg,259MachineInstr *&DefMI) const override;260bool foldImmediate(MachineInstr &UseMI, MachineInstr &DefMI, Register Reg,261MachineRegisterInfo *MRI) const override;262263bool isPredicable(const MachineInstr &MI) const override;264bool isProfitableToIfCvt(MachineBasicBlock &MBB, unsigned NumCycles,265unsigned ExtraPredCycles,266BranchProbability Probability) const override;267bool isProfitableToIfCvt(MachineBasicBlock &TMBB,268unsigned NumCyclesT, unsigned ExtraPredCyclesT,269MachineBasicBlock &FMBB,270unsigned NumCyclesF, unsigned ExtraPredCyclesF,271BranchProbability Probability) const override;272bool isProfitableToDupForIfCvt(MachineBasicBlock &MBB, unsigned NumCycles,273BranchProbability Probability) const override;274bool PredicateInstruction(MachineInstr &MI,275ArrayRef<MachineOperand> Pred) const override;276void copyPhysReg(MachineBasicBlock &MBB, MachineBasicBlock::iterator MBBI,277const DebugLoc &DL, MCRegister DestReg, MCRegister SrcReg,278bool KillSrc) const override;279void storeRegToStackSlot(MachineBasicBlock &MBB,280MachineBasicBlock::iterator MBBI, Register SrcReg,281bool isKill, int FrameIndex,282const TargetRegisterClass *RC,283const TargetRegisterInfo *TRI,284Register VReg) const override;285void loadRegFromStackSlot(MachineBasicBlock &MBB,286MachineBasicBlock::iterator MBBI, Register DestReg,287int FrameIdx, const TargetRegisterClass *RC,288const TargetRegisterInfo *TRI,289Register VReg) const override;290MachineInstr *convertToThreeAddress(MachineInstr &MI, LiveVariables *LV,291LiveIntervals *LIS) const override;292293bool useMachineCombiner() const override { return true; }294bool isAssociativeAndCommutative(const MachineInstr &Inst,295bool Invert) const override;296std::optional<unsigned> getInverseOpcode(unsigned Opcode) const override;297298MachineInstr *299foldMemoryOperandImpl(MachineFunction &MF, MachineInstr &MI,300ArrayRef<unsigned> Ops,301MachineBasicBlock::iterator InsertPt, int FrameIndex,302LiveIntervals *LIS = nullptr,303VirtRegMap *VRM = nullptr) const override;304MachineInstr *foldMemoryOperandImpl(305MachineFunction &MF, MachineInstr &MI, ArrayRef<unsigned> Ops,306MachineBasicBlock::iterator InsertPt, MachineInstr &LoadMI,307LiveIntervals *LIS = nullptr) const override;308bool expandPostRAPseudo(MachineInstr &MBBI) const override;309bool reverseBranchCondition(SmallVectorImpl<MachineOperand> &Cond) const310override;311312// Return the SystemZRegisterInfo, which this class owns.313const SystemZRegisterInfo &getRegisterInfo() const { return RI; }314315// Return the size in bytes of MI.316unsigned getInstSizeInBytes(const MachineInstr &MI) const override;317318// Return true if MI is a conditional or unconditional branch.319// When returning true, set Cond to the mask of condition-code320// values on which the instruction will branch, and set Target321// to the operand that contains the branch target. This target322// can be a register or a basic block.323SystemZII::Branch getBranchInfo(const MachineInstr &MI) const;324325// Get the load and store opcodes for a given register class.326void getLoadStoreOpcodes(const TargetRegisterClass *RC,327unsigned &LoadOpcode, unsigned &StoreOpcode) const;328329// Opcode is the opcode of an instruction that has an address operand,330// and the caller wants to perform that instruction's operation on an331// address that has displacement Offset. Return the opcode of a suitable332// instruction (which might be Opcode itself) or 0 if no such instruction333// exists. MI may be passed in order to allow examination of physical334// register operands (i.e. if a VR32/64 reg ended up as an FP or Vector reg).335unsigned getOpcodeForOffset(unsigned Opcode, int64_t Offset,336const MachineInstr *MI = nullptr) const;337338// Return true if Opcode has a mapping in 12 <-> 20 bit displacements.339bool hasDisplacementPairInsn(unsigned Opcode) const;340341// If Opcode is a load instruction that has a LOAD AND TEST form,342// return the opcode for the testing form, otherwise return 0.343unsigned getLoadAndTest(unsigned Opcode) const;344345// Return true if ROTATE AND ... SELECTED BITS can be used to select bits346// Mask of the R2 operand, given that only the low BitSize bits of Mask are347// significant. Set Start and End to the I3 and I4 operands if so.348bool isRxSBGMask(uint64_t Mask, unsigned BitSize,349unsigned &Start, unsigned &End) const;350351// If Opcode is a COMPARE opcode for which an associated fused COMPARE AND *352// operation exists, return the opcode for the latter, otherwise return 0.353// MI, if nonnull, is the compare instruction.354unsigned getFusedCompare(unsigned Opcode,355SystemZII::FusedCompareType Type,356const MachineInstr *MI = nullptr) const;357358// Try to find all CC users of the compare instruction (MBBI) and update359// all of them to maintain equivalent behavior after swapping the compare360// operands. Return false if not all users can be conclusively found and361// handled. The compare instruction is *not* changed.362bool prepareCompareSwapOperands(MachineBasicBlock::iterator MBBI) const;363364// If Opcode is a LOAD opcode for with an associated LOAD AND TRAP365// operation exists, returh the opcode for the latter, otherwise return 0.366unsigned getLoadAndTrap(unsigned Opcode) const;367368// Emit code before MBBI in MI to move immediate value Value into369// physical register Reg.370void loadImmediate(MachineBasicBlock &MBB,371MachineBasicBlock::iterator MBBI,372unsigned Reg, uint64_t Value) const;373374// Perform target specific instruction verification.375bool verifyInstruction(const MachineInstr &MI,376StringRef &ErrInfo) const override;377378// Sometimes, it is possible for the target to tell, even without379// aliasing information, that two MIs access different memory380// addresses. This function returns true if two MIs access different381// memory addresses and false otherwise.382bool383areMemAccessesTriviallyDisjoint(const MachineInstr &MIa,384const MachineInstr &MIb) const override;385386bool getConstValDefinedInReg(const MachineInstr &MI, const Register Reg,387int64_t &ImmVal) const override;388};389390} // end namespace llvm391392#endif // LLVM_LIB_TARGET_SYSTEMZ_SYSTEMZINSTRINFO_H393394395