2013-10-16 07:44:45 +08:00
|
|
|
//===-- SIInstrInfo.h - SI Instruction Info Interface -----------*- C++ -*-===//
|
2012-12-12 05:25:42 +08:00
|
|
|
//
|
|
|
|
// The LLVM Compiler Infrastructure
|
|
|
|
//
|
|
|
|
// This file is distributed under the University of Illinois Open Source
|
|
|
|
// License. See LICENSE.TXT for details.
|
|
|
|
//
|
|
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
//
|
|
|
|
/// \file
|
|
|
|
/// \brief Interface definition for SIInstrInfo.
|
|
|
|
//
|
|
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
|
|
|
|
|
2016-03-11 16:00:27 +08:00
|
|
|
#ifndef LLVM_LIB_TARGET_AMDGPU_SIINSTRINFO_H
|
|
|
|
#define LLVM_LIB_TARGET_AMDGPU_SIINSTRINFO_H
|
2012-12-12 05:25:42 +08:00
|
|
|
|
|
|
|
#include "AMDGPUInstrInfo.h"
|
2014-12-01 23:52:46 +08:00
|
|
|
#include "SIDefines.h"
|
2012-12-12 05:25:42 +08:00
|
|
|
#include "SIRegisterInfo.h"
|
|
|
|
|
|
|
|
namespace llvm {
|
|
|
|
|
2016-03-11 16:00:27 +08:00
|
|
|
class SIInstrInfo final : public AMDGPUInstrInfo {
|
2012-12-12 05:25:42 +08:00
|
|
|
private:
|
|
|
|
const SIRegisterInfo RI;
|
2016-06-24 14:30:11 +08:00
|
|
|
const SISubtarget &ST;
|
2012-12-12 05:25:42 +08:00
|
|
|
|
2016-05-21 08:29:27 +08:00
|
|
|
// The the inverse predicate should have the negative value.
|
|
|
|
enum BranchPredicate {
|
|
|
|
INVALID_BR = 0,
|
|
|
|
SCC_TRUE = 1,
|
2016-05-21 08:29:40 +08:00
|
|
|
SCC_FALSE = -1,
|
|
|
|
VCCNZ = 2,
|
|
|
|
VCCZ = -2,
|
|
|
|
EXECNZ = -3,
|
|
|
|
EXECZ = 3
|
2016-05-21 08:29:27 +08:00
|
|
|
};
|
|
|
|
|
|
|
|
static unsigned getBranchOpcode(BranchPredicate Cond);
|
|
|
|
static BranchPredicate getBranchPredicate(unsigned Opcode);
|
|
|
|
|
2014-03-21 23:51:57 +08:00
|
|
|
unsigned buildExtractSubReg(MachineBasicBlock::iterator MI,
|
|
|
|
MachineRegisterInfo &MRI,
|
|
|
|
MachineOperand &SuperReg,
|
|
|
|
const TargetRegisterClass *SuperRC,
|
|
|
|
unsigned SubIdx,
|
|
|
|
const TargetRegisterClass *SubRC) const;
|
2014-03-25 04:08:09 +08:00
|
|
|
MachineOperand buildExtractSubRegOrImm(MachineBasicBlock::iterator MI,
|
|
|
|
MachineRegisterInfo &MRI,
|
|
|
|
MachineOperand &SuperReg,
|
|
|
|
const TargetRegisterClass *SuperRC,
|
|
|
|
unsigned SubIdx,
|
|
|
|
const TargetRegisterClass *SubRC) const;
|
2014-03-21 23:51:57 +08:00
|
|
|
|
2016-06-30 08:01:54 +08:00
|
|
|
void swapOperands(MachineInstr &Inst) const;
|
2014-12-07 20:19:03 +08:00
|
|
|
|
2015-11-26 05:22:45 +08:00
|
|
|
void lowerScalarAbs(SmallVectorImpl<MachineInstr *> &Worklist,
|
2016-06-30 08:01:54 +08:00
|
|
|
MachineInstr &Inst) const;
|
2015-11-26 05:22:45 +08:00
|
|
|
|
2014-06-10 00:36:31 +08:00
|
|
|
void splitScalar64BitUnaryOp(SmallVectorImpl<MachineInstr *> &Worklist,
|
2016-06-30 08:01:54 +08:00
|
|
|
MachineInstr &Inst, unsigned Opcode) const;
|
2014-06-10 00:36:31 +08:00
|
|
|
|
|
|
|
void splitScalar64BitBinaryOp(SmallVectorImpl<MachineInstr *> &Worklist,
|
2016-06-30 08:01:54 +08:00
|
|
|
MachineInstr &Inst, unsigned Opcode) const;
|
2014-03-25 04:08:05 +08:00
|
|
|
|
2014-06-11 03:18:24 +08:00
|
|
|
void splitScalar64BitBCNT(SmallVectorImpl<MachineInstr *> &Worklist,
|
2016-06-30 08:01:54 +08:00
|
|
|
MachineInstr &Inst) const;
|
2014-11-15 02:18:16 +08:00
|
|
|
void splitScalar64BitBFE(SmallVectorImpl<MachineInstr *> &Worklist,
|
2016-06-30 08:01:54 +08:00
|
|
|
MachineInstr &Inst) const;
|
2014-06-11 03:18:24 +08:00
|
|
|
|
2015-08-27 04:47:50 +08:00
|
|
|
void addUsersToMoveToVALUWorklist(
|
|
|
|
unsigned Reg, MachineRegisterInfo &MRI,
|
|
|
|
SmallVectorImpl<MachineInstr *> &Worklist) const;
|
|
|
|
|
2016-06-30 08:01:54 +08:00
|
|
|
void
|
|
|
|
addSCCDefUsersToVALUWorklist(MachineInstr &SCCDefInst,
|
|
|
|
SmallVectorImpl<MachineInstr *> &Worklist) const;
|
2016-02-13 07:45:29 +08:00
|
|
|
|
2015-09-29 04:54:57 +08:00
|
|
|
const TargetRegisterClass *
|
|
|
|
getDestEquivalentVGPRClass(const MachineInstr &Inst) const;
|
|
|
|
|
2016-06-30 08:01:54 +08:00
|
|
|
bool checkInstOffsetsDoNotOverlap(MachineInstr &MIa, MachineInstr &MIb) const;
|
2014-11-19 08:01:31 +08:00
|
|
|
|
2016-06-30 08:01:54 +08:00
|
|
|
unsigned findUsedSGPR(const MachineInstr &MI, int OpIndices[3]) const;
|
2014-09-27 01:55:06 +08:00
|
|
|
|
2015-09-29 04:33:22 +08:00
|
|
|
protected:
|
2016-06-30 08:01:54 +08:00
|
|
|
MachineInstr *commuteInstructionImpl(MachineInstr &MI, bool NewMI,
|
2015-09-29 04:33:22 +08:00
|
|
|
unsigned OpIdx0,
|
|
|
|
unsigned OpIdx1) const override;
|
|
|
|
|
2012-12-12 05:25:42 +08:00
|
|
|
public:
|
2016-07-13 22:23:33 +08:00
|
|
|
|
|
|
|
enum TargetOperandFlags {
|
|
|
|
MO_NONE = 0,
|
|
|
|
MO_GOTPCREL = 1
|
|
|
|
};
|
|
|
|
|
2016-06-24 14:30:11 +08:00
|
|
|
explicit SIInstrInfo(const SISubtarget &);
|
2012-12-12 05:25:42 +08:00
|
|
|
|
2016-06-24 14:30:11 +08:00
|
|
|
const SIRegisterInfo &getRegisterInfo() const {
|
2014-03-11 08:01:34 +08:00
|
|
|
return RI;
|
|
|
|
}
|
2012-12-12 05:25:42 +08:00
|
|
|
|
2016-06-30 08:01:54 +08:00
|
|
|
bool isReallyTriviallyReMaterializable(const MachineInstr &MI,
|
2015-04-24 07:34:48 +08:00
|
|
|
AliasAnalysis *AA) const override;
|
|
|
|
|
2014-08-06 08:29:43 +08:00
|
|
|
bool areLoadsFromSameBasePtr(SDNode *Load1, SDNode *Load2,
|
|
|
|
int64_t &Offset1,
|
|
|
|
int64_t &Offset2) const override;
|
|
|
|
|
2016-06-30 08:01:54 +08:00
|
|
|
bool getMemOpBaseRegImmOfs(MachineInstr &LdSt, unsigned &BaseReg,
|
2016-03-10 00:00:35 +08:00
|
|
|
int64_t &Offset,
|
2015-06-16 02:44:14 +08:00
|
|
|
const TargetRegisterInfo *TRI) const final;
|
2014-07-30 05:34:55 +08:00
|
|
|
|
2016-06-30 08:01:54 +08:00
|
|
|
bool shouldClusterMemOps(MachineInstr &FirstLdSt, MachineInstr &SecondLdSt,
|
2016-04-15 22:58:38 +08:00
|
|
|
unsigned NumLoads) const final;
|
2014-09-18 01:48:30 +08:00
|
|
|
|
2016-06-12 23:39:02 +08:00
|
|
|
void copyPhysReg(MachineBasicBlock &MBB, MachineBasicBlock::iterator MI,
|
|
|
|
const DebugLoc &DL, unsigned DestReg, unsigned SrcReg,
|
2014-04-29 15:57:24 +08:00
|
|
|
bool KillSrc) const override;
|
2012-12-12 05:25:42 +08:00
|
|
|
|
2016-06-30 08:01:54 +08:00
|
|
|
unsigned calculateLDSSpillAddress(MachineBasicBlock &MBB, MachineInstr &MI,
|
|
|
|
RegScavenger *RS, unsigned TmpReg,
|
|
|
|
unsigned Offset, unsigned Size) const;
|
2014-09-24 09:33:17 +08:00
|
|
|
|
2013-11-28 05:23:35 +08:00
|
|
|
void storeRegToStackSlot(MachineBasicBlock &MBB,
|
2016-06-30 08:01:54 +08:00
|
|
|
MachineBasicBlock::iterator MI, unsigned SrcReg,
|
|
|
|
bool isKill, int FrameIndex,
|
2013-11-28 05:23:35 +08:00
|
|
|
const TargetRegisterClass *RC,
|
2014-04-29 15:57:24 +08:00
|
|
|
const TargetRegisterInfo *TRI) const override;
|
2013-11-28 05:23:35 +08:00
|
|
|
|
|
|
|
void loadRegFromStackSlot(MachineBasicBlock &MBB,
|
2016-06-30 08:01:54 +08:00
|
|
|
MachineBasicBlock::iterator MI, unsigned DestReg,
|
|
|
|
int FrameIndex, const TargetRegisterClass *RC,
|
2014-04-29 15:57:24 +08:00
|
|
|
const TargetRegisterInfo *TRI) const override;
|
2013-11-28 05:23:35 +08:00
|
|
|
|
2016-06-30 08:01:54 +08:00
|
|
|
bool expandPostRAPseudo(MachineInstr &MI) const override;
|
2014-05-02 23:41:42 +08:00
|
|
|
|
2015-01-08 03:56:17 +08:00
|
|
|
// \brief Returns an opcode that can be used to move a value to a \p DstRC
|
|
|
|
// register. If there is no hardware instruction that can store to \p
|
|
|
|
// DstRC, then AMDGPU::COPY is returned.
|
|
|
|
unsigned getMovOpcode(const TargetRegisterClass *DstRC) const;
|
2015-09-24 15:51:23 +08:00
|
|
|
|
|
|
|
LLVM_READONLY
|
2015-06-27 04:29:10 +08:00
|
|
|
int commuteOpcode(const MachineInstr &MI) const;
|
2013-03-27 17:12:59 +08:00
|
|
|
|
2016-06-30 08:01:54 +08:00
|
|
|
bool findCommutedOpIndices(MachineInstr &MI, unsigned &SrcOpIdx1,
|
2014-09-27 01:54:54 +08:00
|
|
|
unsigned &SrcOpIdx2) const override;
|
2013-02-27 01:52:29 +08:00
|
|
|
|
2016-07-15 22:41:04 +08:00
|
|
|
bool analyzeBranch(MachineBasicBlock &MBB, MachineBasicBlock *&TBB,
|
2016-05-21 08:29:27 +08:00
|
|
|
MachineBasicBlock *&FBB,
|
|
|
|
SmallVectorImpl<MachineOperand> &Cond,
|
|
|
|
bool AllowModify) const override;
|
|
|
|
|
|
|
|
unsigned RemoveBranch(MachineBasicBlock &MBB) const override;
|
|
|
|
|
|
|
|
unsigned InsertBranch(MachineBasicBlock &MBB, MachineBasicBlock *TBB,
|
|
|
|
MachineBasicBlock *FBB, ArrayRef<MachineOperand> Cond,
|
2016-06-12 23:39:02 +08:00
|
|
|
const DebugLoc &DL) const override;
|
2016-05-21 08:29:27 +08:00
|
|
|
|
2016-05-21 08:29:34 +08:00
|
|
|
bool ReverseBranchCondition(
|
|
|
|
SmallVectorImpl<MachineOperand> &Cond) const override;
|
|
|
|
|
2016-06-30 08:01:54 +08:00
|
|
|
bool
|
|
|
|
areMemAccessesTriviallyDisjoint(MachineInstr &MIa, MachineInstr &MIb,
|
|
|
|
AliasAnalysis *AA = nullptr) const override;
|
2014-11-19 08:01:31 +08:00
|
|
|
|
2016-06-30 08:01:54 +08:00
|
|
|
bool FoldImmediate(MachineInstr &UseMI, MachineInstr &DefMI, unsigned Reg,
|
|
|
|
MachineRegisterInfo *MRI) const final;
|
2015-02-22 05:29:07 +08:00
|
|
|
|
2015-05-09 08:56:07 +08:00
|
|
|
unsigned getMachineCSELookAheadLimit() const override { return 500; }
|
|
|
|
|
2015-07-13 23:47:57 +08:00
|
|
|
MachineInstr *convertToThreeAddress(MachineFunction::iterator &MBB,
|
2016-06-30 08:01:54 +08:00
|
|
|
MachineInstr &MI,
|
2015-07-13 23:47:57 +08:00
|
|
|
LiveVariables *LV) const override;
|
|
|
|
|
2016-06-30 08:01:54 +08:00
|
|
|
bool isSchedulingBoundary(const MachineInstr &MI,
|
2016-03-22 04:28:33 +08:00
|
|
|
const MachineBasicBlock *MBB,
|
|
|
|
const MachineFunction &MF) const override;
|
|
|
|
|
2015-10-20 12:35:43 +08:00
|
|
|
static bool isSALU(const MachineInstr &MI) {
|
|
|
|
return MI.getDesc().TSFlags & SIInstrFlags::SALU;
|
|
|
|
}
|
|
|
|
|
2014-12-01 23:52:46 +08:00
|
|
|
bool isSALU(uint16_t Opcode) const {
|
|
|
|
return get(Opcode).TSFlags & SIInstrFlags::SALU;
|
|
|
|
}
|
|
|
|
|
2015-10-20 12:35:43 +08:00
|
|
|
static bool isVALU(const MachineInstr &MI) {
|
|
|
|
return MI.getDesc().TSFlags & SIInstrFlags::VALU;
|
|
|
|
}
|
|
|
|
|
2014-12-01 23:52:46 +08:00
|
|
|
bool isVALU(uint16_t Opcode) const {
|
|
|
|
return get(Opcode).TSFlags & SIInstrFlags::VALU;
|
|
|
|
}
|
|
|
|
|
2016-04-30 08:23:06 +08:00
|
|
|
static bool isVMEM(const MachineInstr &MI) {
|
|
|
|
return isMUBUF(MI) || isMTBUF(MI) || isMIMG(MI);
|
|
|
|
}
|
|
|
|
|
|
|
|
bool isVMEM(uint16_t Opcode) const {
|
|
|
|
return isMUBUF(Opcode) || isMTBUF(Opcode) || isMIMG(Opcode);
|
|
|
|
}
|
|
|
|
|
2015-10-20 12:35:43 +08:00
|
|
|
static bool isSOP1(const MachineInstr &MI) {
|
|
|
|
return MI.getDesc().TSFlags & SIInstrFlags::SOP1;
|
|
|
|
}
|
|
|
|
|
2014-12-01 23:52:46 +08:00
|
|
|
bool isSOP1(uint16_t Opcode) const {
|
|
|
|
return get(Opcode).TSFlags & SIInstrFlags::SOP1;
|
|
|
|
}
|
|
|
|
|
2015-10-20 12:35:43 +08:00
|
|
|
static bool isSOP2(const MachineInstr &MI) {
|
|
|
|
return MI.getDesc().TSFlags & SIInstrFlags::SOP2;
|
|
|
|
}
|
|
|
|
|
2014-12-01 23:52:46 +08:00
|
|
|
bool isSOP2(uint16_t Opcode) const {
|
|
|
|
return get(Opcode).TSFlags & SIInstrFlags::SOP2;
|
|
|
|
}
|
|
|
|
|
2015-10-20 12:35:43 +08:00
|
|
|
static bool isSOPC(const MachineInstr &MI) {
|
|
|
|
return MI.getDesc().TSFlags & SIInstrFlags::SOPC;
|
|
|
|
}
|
|
|
|
|
2014-12-01 23:52:46 +08:00
|
|
|
bool isSOPC(uint16_t Opcode) const {
|
|
|
|
return get(Opcode).TSFlags & SIInstrFlags::SOPC;
|
|
|
|
}
|
|
|
|
|
2015-10-20 12:35:43 +08:00
|
|
|
static bool isSOPK(const MachineInstr &MI) {
|
|
|
|
return MI.getDesc().TSFlags & SIInstrFlags::SOPK;
|
|
|
|
}
|
|
|
|
|
2014-12-01 23:52:46 +08:00
|
|
|
bool isSOPK(uint16_t Opcode) const {
|
|
|
|
return get(Opcode).TSFlags & SIInstrFlags::SOPK;
|
|
|
|
}
|
|
|
|
|
2015-10-20 12:35:43 +08:00
|
|
|
static bool isSOPP(const MachineInstr &MI) {
|
|
|
|
return MI.getDesc().TSFlags & SIInstrFlags::SOPP;
|
|
|
|
}
|
|
|
|
|
2014-12-01 23:52:46 +08:00
|
|
|
bool isSOPP(uint16_t Opcode) const {
|
|
|
|
return get(Opcode).TSFlags & SIInstrFlags::SOPP;
|
|
|
|
}
|
|
|
|
|
2015-10-20 12:35:43 +08:00
|
|
|
static bool isVOP1(const MachineInstr &MI) {
|
|
|
|
return MI.getDesc().TSFlags & SIInstrFlags::VOP1;
|
|
|
|
}
|
|
|
|
|
2014-12-01 23:52:46 +08:00
|
|
|
bool isVOP1(uint16_t Opcode) const {
|
|
|
|
return get(Opcode).TSFlags & SIInstrFlags::VOP1;
|
|
|
|
}
|
|
|
|
|
2015-10-20 12:35:43 +08:00
|
|
|
static bool isVOP2(const MachineInstr &MI) {
|
|
|
|
return MI.getDesc().TSFlags & SIInstrFlags::VOP2;
|
|
|
|
}
|
|
|
|
|
2014-12-01 23:52:46 +08:00
|
|
|
bool isVOP2(uint16_t Opcode) const {
|
|
|
|
return get(Opcode).TSFlags & SIInstrFlags::VOP2;
|
|
|
|
}
|
|
|
|
|
2015-10-20 12:35:43 +08:00
|
|
|
static bool isVOP3(const MachineInstr &MI) {
|
|
|
|
return MI.getDesc().TSFlags & SIInstrFlags::VOP3;
|
|
|
|
}
|
|
|
|
|
2014-12-01 23:52:46 +08:00
|
|
|
bool isVOP3(uint16_t Opcode) const {
|
|
|
|
return get(Opcode).TSFlags & SIInstrFlags::VOP3;
|
|
|
|
}
|
|
|
|
|
2015-10-20 12:35:43 +08:00
|
|
|
static bool isVOPC(const MachineInstr &MI) {
|
|
|
|
return MI.getDesc().TSFlags & SIInstrFlags::VOPC;
|
|
|
|
}
|
|
|
|
|
2014-12-01 23:52:46 +08:00
|
|
|
bool isVOPC(uint16_t Opcode) const {
|
|
|
|
return get(Opcode).TSFlags & SIInstrFlags::VOPC;
|
|
|
|
}
|
|
|
|
|
2015-10-20 12:35:43 +08:00
|
|
|
static bool isMUBUF(const MachineInstr &MI) {
|
|
|
|
return MI.getDesc().TSFlags & SIInstrFlags::MUBUF;
|
|
|
|
}
|
|
|
|
|
2014-12-01 23:52:46 +08:00
|
|
|
bool isMUBUF(uint16_t Opcode) const {
|
|
|
|
return get(Opcode).TSFlags & SIInstrFlags::MUBUF;
|
|
|
|
}
|
|
|
|
|
2015-10-20 12:35:43 +08:00
|
|
|
static bool isMTBUF(const MachineInstr &MI) {
|
|
|
|
return MI.getDesc().TSFlags & SIInstrFlags::MTBUF;
|
|
|
|
}
|
|
|
|
|
2014-12-01 23:52:46 +08:00
|
|
|
bool isMTBUF(uint16_t Opcode) const {
|
|
|
|
return get(Opcode).TSFlags & SIInstrFlags::MTBUF;
|
|
|
|
}
|
|
|
|
|
2015-10-20 12:35:43 +08:00
|
|
|
static bool isSMRD(const MachineInstr &MI) {
|
|
|
|
return MI.getDesc().TSFlags & SIInstrFlags::SMRD;
|
|
|
|
}
|
|
|
|
|
2014-12-01 23:52:46 +08:00
|
|
|
bool isSMRD(uint16_t Opcode) const {
|
|
|
|
return get(Opcode).TSFlags & SIInstrFlags::SMRD;
|
|
|
|
}
|
|
|
|
|
2015-10-20 12:35:43 +08:00
|
|
|
static bool isDS(const MachineInstr &MI) {
|
|
|
|
return MI.getDesc().TSFlags & SIInstrFlags::DS;
|
|
|
|
}
|
|
|
|
|
2014-12-01 23:52:46 +08:00
|
|
|
bool isDS(uint16_t Opcode) const {
|
|
|
|
return get(Opcode).TSFlags & SIInstrFlags::DS;
|
|
|
|
}
|
|
|
|
|
2015-10-20 12:35:43 +08:00
|
|
|
static bool isMIMG(const MachineInstr &MI) {
|
|
|
|
return MI.getDesc().TSFlags & SIInstrFlags::MIMG;
|
|
|
|
}
|
|
|
|
|
2014-12-01 23:52:46 +08:00
|
|
|
bool isMIMG(uint16_t Opcode) const {
|
|
|
|
return get(Opcode).TSFlags & SIInstrFlags::MIMG;
|
|
|
|
}
|
|
|
|
|
2016-07-12 05:59:43 +08:00
|
|
|
static bool isGather4(const MachineInstr &MI) {
|
|
|
|
return MI.getDesc().TSFlags & SIInstrFlags::Gather4;
|
|
|
|
}
|
|
|
|
|
|
|
|
bool isGather4(uint16_t Opcode) const {
|
|
|
|
return get(Opcode).TSFlags & SIInstrFlags::Gather4;
|
|
|
|
}
|
|
|
|
|
2015-10-20 12:35:43 +08:00
|
|
|
static bool isFLAT(const MachineInstr &MI) {
|
|
|
|
return MI.getDesc().TSFlags & SIInstrFlags::FLAT;
|
|
|
|
}
|
|
|
|
|
2014-12-01 23:52:46 +08:00
|
|
|
bool isFLAT(uint16_t Opcode) const {
|
|
|
|
return get(Opcode).TSFlags & SIInstrFlags::FLAT;
|
|
|
|
}
|
2014-11-19 08:01:31 +08:00
|
|
|
|
2015-10-20 12:35:43 +08:00
|
|
|
static bool isWQM(const MachineInstr &MI) {
|
|
|
|
return MI.getDesc().TSFlags & SIInstrFlags::WQM;
|
|
|
|
}
|
|
|
|
|
2015-02-06 10:51:20 +08:00
|
|
|
bool isWQM(uint16_t Opcode) const {
|
|
|
|
return get(Opcode).TSFlags & SIInstrFlags::WQM;
|
|
|
|
}
|
|
|
|
|
2015-10-20 12:35:43 +08:00
|
|
|
static bool isVGPRSpill(const MachineInstr &MI) {
|
|
|
|
return MI.getDesc().TSFlags & SIInstrFlags::VGPRSpill;
|
|
|
|
}
|
|
|
|
|
2015-05-13 02:59:17 +08:00
|
|
|
bool isVGPRSpill(uint16_t Opcode) const {
|
|
|
|
return get(Opcode).TSFlags & SIInstrFlags::VGPRSpill;
|
|
|
|
}
|
|
|
|
|
2016-03-15 01:05:56 +08:00
|
|
|
static bool isDPP(const MachineInstr &MI) {
|
|
|
|
return MI.getDesc().TSFlags & SIInstrFlags::DPP;
|
|
|
|
}
|
|
|
|
|
|
|
|
bool isDPP(uint16_t Opcode) const {
|
|
|
|
return get(Opcode).TSFlags & SIInstrFlags::DPP;
|
|
|
|
}
|
|
|
|
|
2016-07-13 13:55:15 +08:00
|
|
|
static bool isScalarUnit(const MachineInstr &MI) {
|
|
|
|
return MI.getDesc().TSFlags & (SIInstrFlags::SALU | SIInstrFlags::SMRD);
|
|
|
|
}
|
|
|
|
|
|
|
|
static bool usesVM_CNT(const MachineInstr &MI) {
|
|
|
|
return MI.getDesc().TSFlags & SIInstrFlags::VM_CNT;
|
|
|
|
}
|
|
|
|
|
2016-06-25 07:52:11 +08:00
|
|
|
bool isVGPRCopy(const MachineInstr &MI) const {
|
|
|
|
assert(MI.isCopy());
|
|
|
|
unsigned Dest = MI.getOperand(0).getReg();
|
|
|
|
const MachineFunction &MF = *MI.getParent()->getParent();
|
|
|
|
const MachineRegisterInfo &MRI = MF.getRegInfo();
|
|
|
|
return !RI.isSGPRReg(MRI, Dest);
|
|
|
|
}
|
|
|
|
|
2014-04-01 03:54:27 +08:00
|
|
|
bool isInlineConstant(const APInt &Imm) const;
|
2015-02-14 03:05:03 +08:00
|
|
|
bool isInlineConstant(const MachineOperand &MO, unsigned OpSize) const;
|
|
|
|
bool isLiteralConstant(const MachineOperand &MO, unsigned OpSize) const;
|
2013-10-11 01:11:55 +08:00
|
|
|
|
2016-06-30 08:01:54 +08:00
|
|
|
bool isImmOperandLegal(const MachineInstr &MI, unsigned OpNo,
|
2014-07-21 23:45:01 +08:00
|
|
|
const MachineOperand &MO) const;
|
|
|
|
|
2014-08-01 08:32:28 +08:00
|
|
|
/// \brief Return true if this 64-bit VALU instruction has a 32-bit encoding.
|
|
|
|
/// This function will return false if you pass it a 32-bit instruction.
|
|
|
|
bool hasVALU32BitEncoding(unsigned Opcode) const;
|
|
|
|
|
2014-09-24 05:26:25 +08:00
|
|
|
/// \brief Returns true if this operand uses the constant bus.
|
|
|
|
bool usesConstantBus(const MachineRegisterInfo &MRI,
|
2015-02-14 03:05:03 +08:00
|
|
|
const MachineOperand &MO,
|
|
|
|
unsigned OpSize) const;
|
2014-09-24 05:26:25 +08:00
|
|
|
|
2014-08-01 08:32:39 +08:00
|
|
|
/// \brief Return true if this instruction has any modifiers.
|
|
|
|
/// e.g. src[012]_mod, omod, clamp.
|
|
|
|
bool hasModifiers(unsigned Opcode) const;
|
2014-10-18 02:00:43 +08:00
|
|
|
|
|
|
|
bool hasModifiersSet(const MachineInstr &MI,
|
|
|
|
unsigned OpName) const;
|
|
|
|
|
2016-06-30 08:01:54 +08:00
|
|
|
bool verifyInstruction(const MachineInstr &MI,
|
2014-04-29 15:57:24 +08:00
|
|
|
StringRef &ErrInfo) const override;
|
2013-02-07 01:32:29 +08:00
|
|
|
|
2013-11-16 06:02:28 +08:00
|
|
|
static unsigned getVALUOp(const MachineInstr &MI);
|
2014-03-25 04:08:05 +08:00
|
|
|
|
2013-11-14 07:36:37 +08:00
|
|
|
bool isSALUOpSupportedOnVALU(const MachineInstr &MI) const;
|
|
|
|
|
|
|
|
/// \brief Return the correct register class for \p OpNo. For target-specific
|
|
|
|
/// instructions, this will return the register class that has been defined
|
|
|
|
/// in tablegen. For generic instructions, like REG_SEQUENCE it will return
|
|
|
|
/// the register class of its machine operand.
|
|
|
|
/// to infer the correct register class base on the other operands.
|
|
|
|
const TargetRegisterClass *getOpRegClass(const MachineInstr &MI,
|
2015-02-14 03:05:03 +08:00
|
|
|
unsigned OpNo) const;
|
|
|
|
|
|
|
|
/// \brief Return the size in bytes of the operand OpNo on the given
|
|
|
|
// instruction opcode.
|
|
|
|
unsigned getOpSize(uint16_t Opcode, unsigned OpNo) const {
|
|
|
|
const MCOperandInfo &OpInfo = get(Opcode).OpInfo[OpNo];
|
2015-02-22 05:29:04 +08:00
|
|
|
|
|
|
|
if (OpInfo.RegClass == -1) {
|
|
|
|
// If this is an immediate operand, this must be a 32-bit literal.
|
|
|
|
assert(OpInfo.OperandType == MCOI::OPERAND_IMMEDIATE);
|
|
|
|
return 4;
|
|
|
|
}
|
|
|
|
|
2015-02-14 03:05:03 +08:00
|
|
|
return RI.getRegClass(OpInfo.RegClass)->getSize();
|
|
|
|
}
|
|
|
|
|
|
|
|
/// \brief This form should usually be preferred since it handles operands
|
|
|
|
/// with unknown register classes.
|
|
|
|
unsigned getOpSize(const MachineInstr &MI, unsigned OpNo) const {
|
|
|
|
return getOpRegClass(MI, OpNo)->getSize();
|
|
|
|
}
|
2013-11-14 07:36:37 +08:00
|
|
|
|
|
|
|
/// \returns true if it is legal for the operand at index \p OpNo
|
|
|
|
/// to read a VGPR.
|
|
|
|
bool canReadVGPR(const MachineInstr &MI, unsigned OpNo) const;
|
|
|
|
|
|
|
|
/// \brief Legalize the \p OpIndex operand of this instruction by inserting
|
|
|
|
/// a MOV. For example:
|
|
|
|
/// ADD_I32_e32 VGPR0, 15
|
|
|
|
/// to
|
|
|
|
/// MOV VGPR1, 15
|
|
|
|
/// ADD_I32_e32 VGPR0, VGPR1
|
|
|
|
///
|
|
|
|
/// If the operand being legalized is a register, then a COPY will be used
|
|
|
|
/// instead of MOV.
|
2016-06-30 08:01:54 +08:00
|
|
|
void legalizeOpWithMove(MachineInstr &MI, unsigned OpIdx) const;
|
2013-11-14 07:36:37 +08:00
|
|
|
|
2014-08-01 08:32:35 +08:00
|
|
|
/// \brief Check if \p MO is a legal operand if it was the \p OpIdx Operand
|
|
|
|
/// for \p MI.
|
2016-06-30 08:01:54 +08:00
|
|
|
bool isOperandLegal(const MachineInstr &MI, unsigned OpIdx,
|
2014-08-01 08:32:35 +08:00
|
|
|
const MachineOperand *MO = nullptr) const;
|
|
|
|
|
2015-12-02 03:57:17 +08:00
|
|
|
/// \brief Check if \p MO would be a valid operand for the given operand
|
|
|
|
/// definition \p OpInfo. Note this does not attempt to validate constant bus
|
|
|
|
/// restrictions (e.g. literal constant usage).
|
|
|
|
bool isLegalVSrcOperand(const MachineRegisterInfo &MRI,
|
|
|
|
const MCOperandInfo &OpInfo,
|
|
|
|
const MachineOperand &MO) const;
|
|
|
|
|
|
|
|
/// \brief Check if \p MO (a register operand) is a legal register for the
|
|
|
|
/// given operand description.
|
|
|
|
bool isLegalRegOperand(const MachineRegisterInfo &MRI,
|
|
|
|
const MCOperandInfo &OpInfo,
|
|
|
|
const MachineOperand &MO) const;
|
|
|
|
|
|
|
|
/// \brief Legalize operands in \p MI by either commuting it or inserting a
|
|
|
|
/// copy of src1.
|
2016-06-30 08:01:54 +08:00
|
|
|
void legalizeOperandsVOP2(MachineRegisterInfo &MRI, MachineInstr &MI) const;
|
2015-12-02 03:57:17 +08:00
|
|
|
|
2015-10-22 05:51:02 +08:00
|
|
|
/// \brief Fix operands in \p MI to satisfy constant bus requirements.
|
2016-06-30 08:01:54 +08:00
|
|
|
void legalizeOperandsVOP3(MachineRegisterInfo &MRI, MachineInstr &MI) const;
|
2015-10-22 05:51:02 +08:00
|
|
|
|
2016-02-12 05:45:07 +08:00
|
|
|
/// Copy a value from a VGPR (\p SrcReg) to SGPR. This function can only
|
|
|
|
/// be used when it is know that the value in SrcReg is same across all
|
|
|
|
/// threads in the wave.
|
|
|
|
/// \returns The SGPR register that \p SrcReg was copied to.
|
2016-06-30 08:01:54 +08:00
|
|
|
unsigned readlaneVGPRToSGPR(unsigned SrcReg, MachineInstr &UseMI,
|
|
|
|
MachineRegisterInfo &MRI) const;
|
2016-02-12 05:45:07 +08:00
|
|
|
|
2016-06-30 08:01:54 +08:00
|
|
|
void legalizeOperandsSMRD(MachineRegisterInfo &MRI, MachineInstr &MI) const;
|
2016-02-20 08:37:25 +08:00
|
|
|
|
2013-11-14 07:36:37 +08:00
|
|
|
/// \brief Legalize all operands in this instruction. This function may
|
|
|
|
/// create new instruction and insert them before \p MI.
|
2016-06-30 08:01:54 +08:00
|
|
|
void legalizeOperands(MachineInstr &MI) const;
|
2013-11-14 07:36:37 +08:00
|
|
|
|
|
|
|
/// \brief Replace this instruction's opcode with the equivalent VALU
|
|
|
|
/// opcode. This function will also move the users of \p MI to the
|
|
|
|
/// VALU if necessary.
|
|
|
|
void moveToVALU(MachineInstr &MI) const;
|
|
|
|
|
2016-04-07 22:47:07 +08:00
|
|
|
void insertWaitStates(MachineBasicBlock &MBB,MachineBasicBlock::iterator MI,
|
|
|
|
int Count) const;
|
2014-07-22 00:55:33 +08:00
|
|
|
|
2016-04-30 23:18:21 +08:00
|
|
|
void insertNoop(MachineBasicBlock &MBB,
|
|
|
|
MachineBasicBlock::iterator MI) const override;
|
2016-04-30 08:23:06 +08:00
|
|
|
|
|
|
|
/// \brief Return the number of wait states that result from executing this
|
|
|
|
/// instruction.
|
|
|
|
unsigned getNumWaitStates(const MachineInstr &MI) const;
|
|
|
|
|
2014-07-22 00:55:33 +08:00
|
|
|
/// \brief Returns the operand named \p Op. If \p MI does not have an
|
|
|
|
/// operand named \c Op, this function returns nullptr.
|
2015-09-26 02:09:15 +08:00
|
|
|
LLVM_READONLY
|
2014-08-01 08:32:33 +08:00
|
|
|
MachineOperand *getNamedOperand(MachineInstr &MI, unsigned OperandName) const;
|
2014-10-18 02:00:43 +08:00
|
|
|
|
2015-09-26 02:09:15 +08:00
|
|
|
LLVM_READONLY
|
2014-10-18 02:00:43 +08:00
|
|
|
const MachineOperand *getNamedOperand(const MachineInstr &MI,
|
|
|
|
unsigned OpName) const {
|
|
|
|
return getNamedOperand(const_cast<MachineInstr &>(MI), OpName);
|
|
|
|
}
|
2014-12-03 01:05:41 +08:00
|
|
|
|
2015-11-05 10:46:56 +08:00
|
|
|
/// Get required immediate operand
|
|
|
|
int64_t getNamedImmOperand(const MachineInstr &MI, unsigned OpName) const {
|
|
|
|
int Idx = AMDGPU::getNamedOperandIdx(MI.getOpcode(), OpName);
|
|
|
|
return MI.getOperand(Idx).getImm();
|
|
|
|
}
|
|
|
|
|
2014-12-03 01:05:41 +08:00
|
|
|
uint64_t getDefaultRsrcDataFormat() const;
|
2015-09-30 07:37:32 +08:00
|
|
|
uint64_t getScratchRsrcWords23() const;
|
2016-01-14 00:10:10 +08:00
|
|
|
|
2016-06-30 08:01:54 +08:00
|
|
|
bool isLowLatencyInstruction(const MachineInstr &MI) const;
|
|
|
|
bool isHighLatencyInstruction(const MachineInstr &MI) const;
|
2016-01-29 00:04:37 +08:00
|
|
|
|
|
|
|
/// \brief Return the descriptor of the target-specific machine instruction
|
|
|
|
/// that corresponds to the specified pseudo or native opcode.
|
|
|
|
const MCInstrDesc &getMCOpcodeFromPseudo(unsigned Opcode) const {
|
|
|
|
return get(pseudoToMCOpcode(Opcode));
|
|
|
|
}
|
|
|
|
|
2016-06-07 04:10:33 +08:00
|
|
|
unsigned getInstSizeInBytes(const MachineInstr &MI) const;
|
|
|
|
|
2016-01-29 00:04:37 +08:00
|
|
|
ArrayRef<std::pair<int, const char *>>
|
|
|
|
getSerializableTargetIndices() const override;
|
|
|
|
|
2016-04-30 08:23:06 +08:00
|
|
|
ScheduleHazardRecognizer *
|
|
|
|
CreateTargetPostRAHazardRecognizer(const InstrItineraryData *II,
|
|
|
|
const ScheduleDAG *DAG) const override;
|
|
|
|
|
|
|
|
ScheduleHazardRecognizer *
|
|
|
|
CreateTargetPostRAHazardRecognizer(const MachineFunction &MF) const override;
|
2013-11-14 07:36:50 +08:00
|
|
|
};
|
2012-12-12 05:25:42 +08:00
|
|
|
|
2013-02-27 01:52:42 +08:00
|
|
|
namespace AMDGPU {
|
2015-09-24 15:51:23 +08:00
|
|
|
LLVM_READONLY
|
2013-02-27 01:52:42 +08:00
|
|
|
int getVOPe64(uint16_t Opcode);
|
2015-09-24 15:51:23 +08:00
|
|
|
|
|
|
|
LLVM_READONLY
|
2014-07-22 00:55:33 +08:00
|
|
|
int getVOPe32(uint16_t Opcode);
|
2015-09-24 15:51:23 +08:00
|
|
|
|
|
|
|
LLVM_READONLY
|
2013-03-27 17:12:59 +08:00
|
|
|
int getCommuteRev(uint16_t Opcode);
|
2015-09-24 15:51:23 +08:00
|
|
|
|
|
|
|
LLVM_READONLY
|
2013-03-27 17:12:59 +08:00
|
|
|
int getCommuteOrig(uint16_t Opcode);
|
2015-09-24 15:51:23 +08:00
|
|
|
|
|
|
|
LLVM_READONLY
|
2014-08-12 06:18:17 +08:00
|
|
|
int getAddr64Inst(uint16_t Opcode);
|
2015-09-24 15:51:23 +08:00
|
|
|
|
|
|
|
LLVM_READONLY
|
2014-09-08 23:07:27 +08:00
|
|
|
int getAtomicRetOp(uint16_t Opcode);
|
2015-09-24 15:51:23 +08:00
|
|
|
|
|
|
|
LLVM_READONLY
|
2014-09-08 23:07:27 +08:00
|
|
|
int getAtomicNoRetOp(uint16_t Opcode);
|
2013-02-27 01:52:42 +08:00
|
|
|
|
2014-03-21 23:51:57 +08:00
|
|
|
const uint64_t RSRC_DATA_FORMAT = 0xf00000000000LL;
|
2016-06-14 00:05:57 +08:00
|
|
|
const uint64_t RSRC_ELEMENT_SIZE_SHIFT = (32 + 19);
|
|
|
|
const uint64_t RSRC_INDEX_STRIDE_SHIFT = (32 + 21);
|
|
|
|
const uint64_t RSRC_TID_ENABLE = UINT64_C(1) << (32 + 23);
|
2013-02-27 01:52:42 +08:00
|
|
|
} // End namespace AMDGPU
|
|
|
|
|
2014-09-22 23:35:29 +08:00
|
|
|
namespace SI {
|
|
|
|
namespace KernelInputOffsets {
|
|
|
|
|
|
|
|
/// Offsets in bytes from the start of the input buffer
|
|
|
|
enum Offsets {
|
|
|
|
NGROUPS_X = 0,
|
|
|
|
NGROUPS_Y = 4,
|
|
|
|
NGROUPS_Z = 8,
|
|
|
|
GLOBAL_SIZE_X = 12,
|
|
|
|
GLOBAL_SIZE_Y = 16,
|
|
|
|
GLOBAL_SIZE_Z = 20,
|
|
|
|
LOCAL_SIZE_X = 24,
|
|
|
|
LOCAL_SIZE_Y = 28,
|
|
|
|
LOCAL_SIZE_Z = 32
|
|
|
|
};
|
|
|
|
|
|
|
|
} // End namespace KernelInputOffsets
|
|
|
|
} // End namespace SI
|
|
|
|
|
2012-12-12 05:25:42 +08:00
|
|
|
} // End namespace llvm
|
|
|
|
|
2014-08-14 00:26:38 +08:00
|
|
|
#endif
|