#ifndef LLVM_LIB_TARGET_SYSTEMZ_SYSTEMZINSTRINFO_H
#define LLVM_LIB_TARGET_SYSTEMZ_SYSTEMZINSTRINFO_H
#include "SystemZ.h"
#include "SystemZRegisterInfo.h"
#include "llvm/ADT/ArrayRef.h"
#include "llvm/CodeGen/MachineBasicBlock.h"
#include "llvm/CodeGen/MachineFunction.h"
#include "llvm/CodeGen/MachineInstrBuilder.h"
#include "llvm/CodeGen/TargetInstrInfo.h"
#include <cstdint>
#define GET_INSTRINFO_HEADER
#include "SystemZGenInstrInfo.inc"
namespace llvm {
class SystemZSubtarget;
namespace SystemZII {
enum {
SimpleBDXLoad = (1 << 0),
SimpleBDXStore = (1 << 1),
Has20BitOffset = (1 << 2),
HasIndex = (1 << 3),
Is128Bit = (1 << 4),
AccessSizeMask = (31 << 5),
AccessSizeShift = 5,
CCValuesMask = (15 << 10),
CCValuesShift = 10,
CompareZeroCCMaskMask = (15 << 14),
CompareZeroCCMaskShift = 14,
CCMaskFirst = (1 << 18),
CCMaskLast = (1 << 19),
IsLogical = (1 << 20),
CCIfNoSignedWrap = (1 << 21)
};
static inline unsigned getAccessSize(unsigned int Flags) {
return (Flags & AccessSizeMask) >> AccessSizeShift;
}
static inline unsigned getCCValues(unsigned int Flags) {
return (Flags & CCValuesMask) >> CCValuesShift;
}
static inline unsigned getCompareZeroCCMask(unsigned int Flags) {
return (Flags & CompareZeroCCMaskMask) >> CompareZeroCCMaskShift;
}
enum {
MO_SYMBOL_MODIFIER = (3 << 0),
MO_GOT = (1 << 0),
MO_INDNTPOFF = (2 << 0)
};
enum BranchType {
BranchNormal,
BranchC,
BranchCL,
BranchCG,
BranchCLG,
BranchCT,
BranchCTG,
AsmGoto
};
class Branch {
const MachineOperand *Target;
public:
BranchType Type;
unsigned CCValid;
unsigned CCMask;
Branch(BranchType type, unsigned ccValid, unsigned ccMask,
const MachineOperand *target)
: Target(target), Type(type), CCValid(ccValid), CCMask(ccMask) {}
bool isIndirect() { return Target != nullptr && Target->isReg(); }
bool hasMBBTarget() { return Target != nullptr && Target->isMBB(); }
MachineBasicBlock *getMBBTarget() {
return hasMBBTarget() ? Target->getMBB() : nullptr;
}
};
enum FusedCompareType {
CompareAndBranch,
CompareAndReturn,
CompareAndSibcall,
CompareAndTrap
};
}
namespace SystemZ {
int getTwoOperandOpcode(uint16_t Opcode);
int getTargetMemOpcode(uint16_t Opcode);
unsigned reverseCCMask(unsigned CCMask);
MachineBasicBlock *emitBlockAfter(MachineBasicBlock *MBB);
MachineBasicBlock *splitBlockAfter(MachineBasicBlock::iterator MI,
MachineBasicBlock *MBB);
MachineBasicBlock *splitBlockBefore(MachineBasicBlock::iterator MI,
MachineBasicBlock *MBB);
}
class SystemZInstrInfo : public SystemZGenInstrInfo {
const SystemZRegisterInfo RI;
SystemZSubtarget &STI;
void splitMove(MachineBasicBlock::iterator MI, unsigned NewOpcode) const;
void splitAdjDynAlloc(MachineBasicBlock::iterator MI) const;
void expandRIPseudo(MachineInstr &MI, unsigned LowOpcode, unsigned HighOpcode,
bool ConvertHigh) const;
void expandRIEPseudo(MachineInstr &MI, unsigned LowOpcode,
unsigned LowOpcodeK, unsigned HighOpcode) const;
void expandRXYPseudo(MachineInstr &MI, unsigned LowOpcode,
unsigned HighOpcode) const;
void expandLOCPseudo(MachineInstr &MI, unsigned LowOpcode,
unsigned HighOpcode) const;
void expandZExtPseudo(MachineInstr &MI, unsigned LowOpcode,
unsigned Size) const;
void expandLoadStackGuard(MachineInstr *MI) const;
MachineInstrBuilder
emitGRX32Move(MachineBasicBlock &MBB, MachineBasicBlock::iterator MBBI,
const DebugLoc &DL, unsigned DestReg, unsigned SrcReg,
unsigned LowLowOpcode, unsigned Size, bool KillSrc,
bool UndefSrc) const;
virtual void anchor();
protected:
MachineInstr *commuteInstructionImpl(MachineInstr &MI, bool NewMI,
unsigned CommuteOpIdx1,
unsigned CommuteOpIdx2) const override;
public:
explicit SystemZInstrInfo(SystemZSubtarget &STI);
unsigned isLoadFromStackSlot(const MachineInstr &MI,
int &FrameIndex) const override;
unsigned isStoreToStackSlot(const MachineInstr &MI,
int &FrameIndex) const override;
bool isStackSlotCopy(const MachineInstr &MI, int &DestFrameIndex,
int &SrcFrameIndex) const override;
bool analyzeBranch(MachineBasicBlock &MBB, MachineBasicBlock *&TBB,
MachineBasicBlock *&FBB,
SmallVectorImpl<MachineOperand> &Cond,
bool AllowModify) const override;
unsigned removeBranch(MachineBasicBlock &MBB,
int *BytesRemoved = nullptr) const override;
unsigned insertBranch(MachineBasicBlock &MBB, MachineBasicBlock *TBB,
MachineBasicBlock *FBB, ArrayRef<MachineOperand> Cond,
const DebugLoc &DL,
int *BytesAdded = nullptr) const override;
bool analyzeCompare(const MachineInstr &MI, Register &SrcReg,
Register &SrcReg2, int64_t &Mask,
int64_t &Value) const override;
bool canInsertSelect(const MachineBasicBlock &, ArrayRef<MachineOperand> Cond,
Register, Register, Register, int &, int &,
int &) const override;
void insertSelect(MachineBasicBlock &MBB, MachineBasicBlock::iterator MI,
const DebugLoc &DL, Register DstReg,
ArrayRef<MachineOperand> Cond, Register TrueReg,
Register FalseReg) const override;
bool FoldImmediate(MachineInstr &UseMI, MachineInstr &DefMI, Register Reg,
MachineRegisterInfo *MRI) const override;
bool isPredicable(const MachineInstr &MI) const override;
bool isProfitableToIfCvt(MachineBasicBlock &MBB, unsigned NumCycles,
unsigned ExtraPredCycles,
BranchProbability Probability) const override;
bool isProfitableToIfCvt(MachineBasicBlock &TMBB,
unsigned NumCyclesT, unsigned ExtraPredCyclesT,
MachineBasicBlock &FMBB,
unsigned NumCyclesF, unsigned ExtraPredCyclesF,
BranchProbability Probability) const override;
bool isProfitableToDupForIfCvt(MachineBasicBlock &MBB, unsigned NumCycles,
BranchProbability Probability) const override;
bool PredicateInstruction(MachineInstr &MI,
ArrayRef<MachineOperand> Pred) const override;
void copyPhysReg(MachineBasicBlock &MBB, MachineBasicBlock::iterator MBBI,
const DebugLoc &DL, MCRegister DestReg, MCRegister SrcReg,
bool KillSrc) const override;
void storeRegToStackSlot(MachineBasicBlock &MBB,
MachineBasicBlock::iterator MBBI,
Register SrcReg, bool isKill, int FrameIndex,
const TargetRegisterClass *RC,
const TargetRegisterInfo *TRI) const override;
void loadRegFromStackSlot(MachineBasicBlock &MBB,
MachineBasicBlock::iterator MBBI,
Register DestReg, int FrameIdx,
const TargetRegisterClass *RC,
const TargetRegisterInfo *TRI) const override;
MachineInstr *convertToThreeAddress(MachineInstr &MI, LiveVariables *LV,
LiveIntervals *LIS) const override;
MachineInstr *
foldMemoryOperandImpl(MachineFunction &MF, MachineInstr &MI,
ArrayRef<unsigned> Ops,
MachineBasicBlock::iterator InsertPt, int FrameIndex,
LiveIntervals *LIS = nullptr,
VirtRegMap *VRM = nullptr) const override;
MachineInstr *foldMemoryOperandImpl(
MachineFunction &MF, MachineInstr &MI, ArrayRef<unsigned> Ops,
MachineBasicBlock::iterator InsertPt, MachineInstr &LoadMI,
LiveIntervals *LIS = nullptr) const override;
bool expandPostRAPseudo(MachineInstr &MBBI) const override;
bool reverseBranchCondition(SmallVectorImpl<MachineOperand> &Cond) const
override;
const SystemZRegisterInfo &getRegisterInfo() const { return RI; }
unsigned getInstSizeInBytes(const MachineInstr &MI) const override;
SystemZII::Branch getBranchInfo(const MachineInstr &MI) const;
void getLoadStoreOpcodes(const TargetRegisterClass *RC,
unsigned &LoadOpcode, unsigned &StoreOpcode) const;
unsigned getOpcodeForOffset(unsigned Opcode, int64_t Offset,
const MachineInstr *MI = nullptr) const;
bool hasDisplacementPairInsn(unsigned Opcode) const;
unsigned getLoadAndTest(unsigned Opcode) const;
bool isRxSBGMask(uint64_t Mask, unsigned BitSize,
unsigned &Start, unsigned &End) const;
unsigned getFusedCompare(unsigned Opcode,
SystemZII::FusedCompareType Type,
const MachineInstr *MI = nullptr) const;
bool prepareCompareSwapOperands(MachineBasicBlock::iterator MBBI) const;
unsigned getLoadAndTrap(unsigned Opcode) const;
void loadImmediate(MachineBasicBlock &MBB,
MachineBasicBlock::iterator MBBI,
unsigned Reg, uint64_t Value) const;
bool verifyInstruction(const MachineInstr &MI,
StringRef &ErrInfo) const override;
bool
areMemAccessesTriviallyDisjoint(const MachineInstr &MIa,
const MachineInstr &MIb) const override;
};
}
#endif