Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
10 changes: 5 additions & 5 deletions llvm/lib/Target/AMDGPU/SIDefines.h
Original file line number Diff line number Diff line change
Expand Up @@ -237,24 +237,24 @@ enum OperandType : unsigned {
OPERAND_REG_INLINE_AC_FP32,
OPERAND_REG_INLINE_AC_FP64,

// Operand for AV_MOV_B64_IMM_PSEUDO, which is a pair of 32-bit inline
// constants. Does not accept registers.
OPERAND_INLINE_C_AV64_PSEUDO,

// Operand for source modifiers for VOP instructions
OPERAND_INPUT_MODS,

// Operand for SDWA instructions
OPERAND_SDWA_VOPC_DST,

// Operand for AV_MOV_B64_IMM_PSEUDO, which is a pair of 32-bit inline
// constants.
OPERAND_INLINE_C_AV64_PSEUDO,

OPERAND_REG_IMM_FIRST = OPERAND_REG_IMM_INT32,
OPERAND_REG_IMM_LAST = OPERAND_REG_IMM_V2FP32,

OPERAND_REG_INLINE_C_FIRST = OPERAND_REG_INLINE_C_INT16,
OPERAND_REG_INLINE_C_LAST = OPERAND_REG_INLINE_AC_FP64,

OPERAND_REG_INLINE_AC_FIRST = OPERAND_REG_INLINE_AC_INT32,
OPERAND_REG_INLINE_AC_LAST = OPERAND_REG_INLINE_AC_FP64,
OPERAND_REG_INLINE_AC_LAST = OPERAND_INLINE_C_AV64_PSEUDO,

OPERAND_SRC_FIRST = OPERAND_REG_IMM_INT32,
OPERAND_SRC_LAST = OPERAND_REG_INLINE_C_LAST,
Expand Down
25 changes: 19 additions & 6 deletions llvm/lib/Target/AMDGPU/SIFoldOperands.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1296,7 +1296,8 @@ void SIFoldOperandsImpl::foldOperand(
for (unsigned MovOp :
{AMDGPU::S_MOV_B32, AMDGPU::V_MOV_B32_e32, AMDGPU::S_MOV_B64,
AMDGPU::V_MOV_B64_PSEUDO, AMDGPU::V_MOV_B16_t16_e64,
AMDGPU::V_ACCVGPR_WRITE_B32_e64, AMDGPU::AV_MOV_B32_IMM_PSEUDO}) {
AMDGPU::V_ACCVGPR_WRITE_B32_e64, AMDGPU::AV_MOV_B32_IMM_PSEUDO,
AMDGPU::AV_MOV_B64_IMM_PSEUDO}) {
const MCInstrDesc &MovDesc = TII->get(MovOp);
assert(MovDesc.getNumDefs() > 0 && MovDesc.operands()[0].RegClass != -1);

Expand All @@ -1312,11 +1313,23 @@ void SIFoldOperandsImpl::foldOperand(
const int SrcIdx = MovOp == AMDGPU::V_MOV_B16_t16_e64 ? 2 : 1;
const TargetRegisterClass *MovSrcRC =
TRI->getRegClass(MovDesc.operands()[SrcIdx].RegClass);

if (UseSubReg)
MovSrcRC = TRI->getMatchingSuperRegClass(SrcRC, MovSrcRC, UseSubReg);
if (!MRI->constrainRegClass(SrcReg, MovSrcRC))
break;
if (MovSrcRC) {
if (UseSubReg)
MovSrcRC = TRI->getMatchingSuperRegClass(SrcRC, MovSrcRC, UseSubReg);
if (!MRI->constrainRegClass(SrcReg, MovSrcRC))
break;

// FIXME: This is mutating the instruction only and deferring the actual
// fold of the immediate
} else {
// For the _IMM_PSEUDO cases, there can be value restrictions on the
// immediate to verify. Technically we should always verify this, but it
// only matters for these concrete cases.
// TODO: Handle non-imm case if it's useful.
if (!OpToFold.isImm() ||
!TII->isImmOperandLegal(MovDesc, 1, *OpToFold.getEffectiveImmVal()))
break;
}

MachineInstr::mop_iterator ImpOpI = UseMI->implicit_operands().begin();
MachineInstr::mop_iterator ImpOpE = UseMI->implicit_operands().end();
Expand Down
102 changes: 59 additions & 43 deletions llvm/lib/Target/AMDGPU/SIInstrInfo.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -3444,12 +3444,8 @@ bool SIInstrInfo::isFoldableCopy(const MachineInstr &MI) {
case AMDGPU::V_ACCVGPR_READ_B32_e64:
case AMDGPU::V_ACCVGPR_MOV_B32:
case AMDGPU::AV_MOV_B32_IMM_PSEUDO:
return true;
case AMDGPU::AV_MOV_B64_IMM_PSEUDO:
// TODO: We could fold this, but it's a strange case. The immediate value
// can't be directly folded into any real use. We would have to spread new
// immediate legality checks around and only accept subregister extracts for
// profitability.
return true;
default:
return false;
}
Expand Down Expand Up @@ -4572,33 +4568,43 @@ static bool compareMachineOp(const MachineOperand &Op0,
}
}

bool SIInstrInfo::isImmOperandLegal(const MCInstrDesc &InstDesc, unsigned OpNo,
const MachineOperand &MO) const {
const MCOperandInfo &OpInfo = InstDesc.operands()[OpNo];

assert(MO.isImm() || MO.isTargetIndex() || MO.isFI() || MO.isGlobal());

bool SIInstrInfo::isLiteralOperandLegal(const MCInstrDesc &InstDesc,
const MCOperandInfo &OpInfo) const {
if (OpInfo.OperandType == MCOI::OPERAND_IMMEDIATE)
return true;

if (OpInfo.RegClass < 0)
if (!RI.opCanUseLiteralConstant(OpInfo.OperandType))
return false;

if (MO.isImm() && isInlineConstant(MO, OpInfo)) {
if (!isVOP3(InstDesc) || !AMDGPU::isSISrcOperand(OpInfo))
return true;

return ST.hasVOP3Literal();
}

bool SIInstrInfo::isImmOperandLegal(const MCInstrDesc &InstDesc, unsigned OpNo,
int64_t ImmVal) const {
const MCOperandInfo &OpInfo = InstDesc.operands()[OpNo];
if (isInlineConstant(ImmVal, OpInfo.OperandType)) {
if (isMAI(InstDesc) && ST.hasMFMAInlineLiteralBug() &&
OpNo == (unsigned)AMDGPU::getNamedOperandIdx(InstDesc.getOpcode(),
AMDGPU::OpName::src2))
return false;
return RI.opCanUseInlineConstant(OpInfo.OperandType);
}

if (!RI.opCanUseLiteralConstant(OpInfo.OperandType))
return false;
return isLiteralOperandLegal(InstDesc, OpInfo);
}

if (!isVOP3(InstDesc) || !AMDGPU::isSISrcOperand(InstDesc, OpNo))
return true;
bool SIInstrInfo::isImmOperandLegal(const MCInstrDesc &InstDesc, unsigned OpNo,
const MachineOperand &MO) const {
if (MO.isImm())
return isImmOperandLegal(InstDesc, OpNo, MO.getImm());

return ST.hasVOP3Literal();
assert((MO.isTargetIndex() || MO.isFI() || MO.isGlobal()) &&
"unexpected imm-like operand kind");
const MCOperandInfo &OpInfo = InstDesc.operands()[OpNo];
return isLiteralOperandLegal(InstDesc, OpInfo);
}

bool SIInstrInfo::isLegalAV64PseudoImm(uint64_t Imm) const {
Expand Down Expand Up @@ -4758,30 +4764,41 @@ MachineInstr *SIInstrInfo::buildShrunkInst(MachineInstr &MI,
return Inst32;
}

bool SIInstrInfo::physRegUsesConstantBus(const MachineOperand &RegOp) const {
// Null is free
Register Reg = RegOp.getReg();
if (Reg == AMDGPU::SGPR_NULL || Reg == AMDGPU::SGPR_NULL64)
return false;

// SGPRs use the constant bus

// FIXME: implicit registers that are not part of the MCInstrDesc's implicit
// physical register operands should also count, except for exec.
if (RegOp.isImplicit())
return Reg == AMDGPU::VCC || Reg == AMDGPU::VCC_LO || Reg == AMDGPU::M0;

// SGPRs use the constant bus
return AMDGPU::SReg_32RegClass.contains(Reg) ||
AMDGPU::SReg_64RegClass.contains(Reg);
}

bool SIInstrInfo::regUsesConstantBus(const MachineOperand &RegOp,
const MachineRegisterInfo &MRI) const {
Register Reg = RegOp.getReg();
return Reg.isVirtual() ? RI.isSGPRClass(MRI.getRegClass(Reg))
: physRegUsesConstantBus(RegOp);
}

bool SIInstrInfo::usesConstantBus(const MachineRegisterInfo &MRI,
const MachineOperand &MO,
const MCOperandInfo &OpInfo) const {
// Literal constants use the constant bus.
if (!MO.isReg())
return !isInlineConstant(MO, OpInfo);

if (!MO.isUse())
return false;

if (MO.getReg().isVirtual())
return RI.isSGPRClass(MRI.getRegClass(MO.getReg()));

// Null is free
if (MO.getReg() == AMDGPU::SGPR_NULL || MO.getReg() == AMDGPU::SGPR_NULL64)
return false;

// SGPRs use the constant bus
if (MO.isImplicit()) {
return MO.getReg() == AMDGPU::M0 || MO.getReg() == AMDGPU::VCC ||
MO.getReg() == AMDGPU::VCC_LO;
}
return AMDGPU::SReg_32RegClass.contains(MO.getReg()) ||
AMDGPU::SReg_64RegClass.contains(MO.getReg());
Register Reg = MO.getReg();
return Reg.isVirtual() ? RI.isSGPRClass(MRI.getRegClass(Reg))
: physRegUsesConstantBus(MO);
}

static Register findImplicitSGPRRead(const MachineInstr &MI) {
Expand Down Expand Up @@ -6250,15 +6267,14 @@ bool SIInstrInfo::isOperandLegal(const MachineInstr &MI, unsigned OpIdx,
continue;
const MachineOperand &Op = MI.getOperand(i);
if (Op.isReg()) {
RegSubRegPair SGPR(Op.getReg(), Op.getSubReg());
if (!SGPRsUsed.count(SGPR) &&
// FIXME: This can access off the end of the operands() array.
usesConstantBus(MRI, Op, InstDesc.operands().begin()[i])) {
if (--ConstantBusLimit <= 0)
return false;
SGPRsUsed.insert(SGPR);
if (Op.isUse()) {
RegSubRegPair SGPR(Op.getReg(), Op.getSubReg());
if (regUsesConstantBus(Op, MRI) && SGPRsUsed.insert(SGPR).second) {
if (--ConstantBusLimit <= 0)
return false;
}
}
} else if (AMDGPU::isSISrcOperand(InstDesc, i) &&
} else if (AMDGPU::isSISrcOperand(InstDesc.operands()[i]) &&
!isInlineConstant(Op, InstDesc.operands()[i])) {
// The same literal may be used multiple times.
if (!UsedLiteral)
Expand Down
10 changes: 10 additions & 0 deletions llvm/lib/Target/AMDGPU/SIInstrInfo.h
Original file line number Diff line number Diff line change
Expand Up @@ -1183,6 +1183,12 @@ class SIInstrInfo final : public AMDGPUGenInstrInfo {
bool isImmOperandLegal(const MCInstrDesc &InstDesc, unsigned OpNo,
const MachineOperand &MO) const;

bool isLiteralOperandLegal(const MCInstrDesc &InstDesc,
const MCOperandInfo &OpInfo) const;

bool isImmOperandLegal(const MCInstrDesc &InstDesc, unsigned OpNo,
int64_t ImmVal) const;

bool isImmOperandLegal(const MachineInstr &MI, unsigned OpNo,
const MachineOperand &MO) const {
return isImmOperandLegal(MI.getDesc(), OpNo, MO);
Expand All @@ -1195,6 +1201,10 @@ class SIInstrInfo final : public AMDGPUGenInstrInfo {
/// This function will return false if you pass it a 32-bit instruction.
bool hasVALU32BitEncoding(unsigned Opcode) const;

bool physRegUsesConstantBus(const MachineOperand &Reg) const;
bool regUsesConstantBus(const MachineOperand &Reg,
const MachineRegisterInfo &MRI) const;

/// Returns true if this operand uses the constant bus.
bool usesConstantBus(const MachineRegisterInfo &MRI,
const MachineOperand &MO,
Expand Down
7 changes: 0 additions & 7 deletions llvm/lib/Target/AMDGPU/Utils/AMDGPUBaseInfo.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2720,13 +2720,6 @@ bool isInlineValue(unsigned Reg) {
#undef CASE_GFXPRE11_GFX11PLUS_TO
#undef MAP_REG2REG

bool isSISrcOperand(const MCInstrDesc &Desc, unsigned OpNo) {
assert(OpNo < Desc.NumOperands);
unsigned OpType = Desc.operands()[OpNo].OperandType;
return OpType >= AMDGPU::OPERAND_SRC_FIRST &&
OpType <= AMDGPU::OPERAND_SRC_LAST;
}

bool isKImmOperand(const MCInstrDesc &Desc, unsigned OpNo) {
assert(OpNo < Desc.NumOperands);
unsigned OpType = Desc.operands()[OpNo].OperandType;
Expand Down
9 changes: 8 additions & 1 deletion llvm/lib/Target/AMDGPU/Utils/AMDGPUBaseInfo.h
Original file line number Diff line number Diff line change
Expand Up @@ -1590,7 +1590,14 @@ bool isInlineValue(unsigned Reg);

/// Is this an AMDGPU specific source operand? These include registers,
/// inline constants, literals and mandatory literals (KImm).
bool isSISrcOperand(const MCInstrDesc &Desc, unsigned OpNo);
constexpr bool isSISrcOperand(const MCOperandInfo &OpInfo) {
return OpInfo.OperandType >= AMDGPU::OPERAND_SRC_FIRST &&
OpInfo.OperandType <= AMDGPU::OPERAND_SRC_LAST;
}

constexpr bool isSISrcOperand(const MCInstrDesc &Desc, unsigned OpNo) {
return isSISrcOperand(Desc.operands()[OpNo]);
}

/// Is this a KImm operand?
bool isKImmOperand(const MCInstrDesc &Desc, unsigned OpNo);
Expand Down
Loading
Loading