Skip to content

Commit

Permalink
[AMDGPU][GFX11] Refactor VOPD operands handling
Browse files Browse the repository at this point in the history
Differential Revision: https://reviews.llvm.org/D137952
  • Loading branch information
dpreobra committed Nov 16, 2022
1 parent 7160987 commit e468b1b
Show file tree
Hide file tree
Showing 4 changed files with 87 additions and 73 deletions.
12 changes: 6 additions & 6 deletions llvm/lib/Target/AMDGPU/AsmParser/AMDGPUAsmParser.cpp
Expand Up @@ -3590,7 +3590,7 @@ bool AMDGPUAsmParser::validateVOPDRegBankConstraints(
: MCRegister::NoRegister;
};

auto InstInfo = getVOPDInstInfo(Opcode, &MII);
const auto &InstInfo = getVOPDInstInfo(Opcode, &MII);
auto InvalidOperandInfo = InstInfo.getInvalidOperandIndex(getVRegIdx);
if (!InvalidOperandInfo)
return true;
Expand Down Expand Up @@ -8524,11 +8524,11 @@ void AMDGPUAsmParser::cvtVOPD(MCInst &Inst, const OperandVector &Operands) {

for (auto CompIdx : VOPD::COMPONENTS) {
const auto &CInfo = InstInfo[CompIdx];
bool CompHasSrc2Acc = CInfo.hasSrc2Acc();
auto SrcOperandsNum = InstInfo[CompIdx].getSrcOperandsNum();
for (unsigned SrcIdx = 0; SrcIdx < SrcOperandsNum; ++SrcIdx) {
addOp(CInfo.getParsedSrcIndex(SrcIdx, CompHasSrc2Acc));
}
auto ParsedSrcOperandsNum = InstInfo[CompIdx].getParsedSrcOperandsNum();
for (unsigned SrcIdx = 0; SrcIdx < ParsedSrcOperandsNum; ++SrcIdx)
addOp(CInfo.getParsedSrcIndex(SrcIdx));
if (CInfo.hasSrc2Acc())
addOp(CInfo.getParsedDstIndex());
}
}

Expand Down
35 changes: 19 additions & 16 deletions llvm/lib/Target/AMDGPU/Utils/AMDGPUBaseInfo.cpp
Expand Up @@ -499,8 +499,8 @@ unsigned ComponentInfo::getParsedOperandIndex(unsigned OprIdx) const {
return getParsedDstIndex();

auto SrcIdx = OprIdx - Component::DST_NUM;
if (SrcIdx < getSrcOperandsNum())
return getParsedSrcIndex(SrcIdx, hasSrc2Acc());
if (SrcIdx < getParsedSrcOperandsNum())
return getParsedSrcIndex(SrcIdx);

// The specified operand does not exist.
return 0;
Expand All @@ -522,25 +522,30 @@ Optional<unsigned> InstInfo::getInvalidOperandIndex(
return {};
}

// Return an array of VGPR registers [DST,SRC0,SRC1,SRC2] used
// by the specified component. If an operand is unused
// or is not a VGPR, the corresponding value is 0.
//
// GetRegIdx(Component, OperandIdx) must return a VGPR register index
// for the specified component and operand. The callback must return 0
// if the operand is not a register or not a VGPR.
InstInfo::RegIndices InstInfo::getRegIndices(
unsigned ComponentIdx,
std::function<unsigned(unsigned, unsigned)> GetRegIdx) const {
assert(ComponentIdx < COMPONENTS_NUM);

auto Comp = CompInfo[ComponentIdx];
InstInfo::RegIndices RegIndices;

unsigned DstReg = GetRegIdx(ComponentIdx, Comp.getDstIndex());
unsigned Src0Reg = GetRegIdx(ComponentIdx, Comp.getSrcIndex(0));

unsigned Src1Reg = 0;
if (Comp.hasRegularSrcOperand(1))
Src1Reg = GetRegIdx(ComponentIdx, Comp.getSrcIndex(1));
RegIndices[DST] = GetRegIdx(ComponentIdx, Comp.getDstIndex());

unsigned Src2Reg = 0;
if (Comp.hasRegularSrcOperand(2))
Src2Reg = GetRegIdx(ComponentIdx, Comp.getSrcIndex(2));

return {DstReg, Src0Reg, Src1Reg, Src2Reg};
for (unsigned OprIdx : {SRC0, SRC1, SRC2}) {
unsigned SrcIdx = OprIdx - DST_NUM;
RegIndices[OprIdx] = Comp.hasRegSrcOperand(SrcIdx)
? GetRegIdx(ComponentIdx, Comp.getSrcIndex(SrcIdx))
: 0;
}
return RegIndices;
}

} // namespace VOPD
Expand All @@ -555,9 +560,7 @@ VOPD::InstInfo getVOPDInstInfo(unsigned VOPDOpcode,
const auto &OpXDesc = InstrInfo->get(OpX);
const auto &OpYDesc = InstrInfo->get(OpY);
VOPD::ComponentInfo OpXInfo(OpXDesc, VOPD::ComponentKind::COMPONENT_X);
VOPD::ComponentInfo OpYInfo(
OpYDesc, VOPD::ComponentKind::COMPONENT_Y, OpXInfo.getSrcOperandsNum(),
OpXInfo.getSrcOperandsNum() - OpXInfo.hasSrc2Acc());
VOPD::ComponentInfo OpYInfo(OpYDesc, OpXInfo);
return VOPD::InstInfo(OpXInfo, OpYInfo);
}

Expand Down
111 changes: 61 additions & 50 deletions llvm/lib/Target/AMDGPU/Utils/AMDGPUBaseInfo.h
Expand Up @@ -529,6 +529,40 @@ enum ComponentIndex : unsigned { X = 0, Y = 1 };
constexpr unsigned COMPONENTS[] = {ComponentIndex::X, ComponentIndex::Y};
constexpr unsigned COMPONENTS_NUM = 2;

// Properties of VOPD components.
class ComponentProps {
private:
unsigned SrcOperandsNum = 0;
Optional<unsigned> MandatoryLiteralIdx;
bool HasSrc2Acc = false;

public:
ComponentProps() = default;
ComponentProps(const MCInstrDesc &OpDesc);

unsigned getSrcOperandsNum() const { return SrcOperandsNum; }
unsigned getParsedSrcOperandsNum() const {
return SrcOperandsNum - HasSrc2Acc;
}
bool hasMandatoryLiteral() const { return MandatoryLiteralIdx.has_value(); }
unsigned getMandatoryLiteralIndex() const {
assert(hasMandatoryLiteral());
return *MandatoryLiteralIdx;
}
bool hasRegSrcOperand(unsigned SrcIdx) const {
assert(SrcIdx < Component::MAX_SRC_NUM);
return SrcOperandsNum > SrcIdx && !hasMandatoryLiteralAt(SrcIdx);
}
bool hasSrc2Acc() const { return HasSrc2Acc; }

private:
bool hasMandatoryLiteralAt(unsigned SrcIdx) const {
assert(SrcIdx < Component::MAX_SRC_NUM);
return hasMandatoryLiteral() &&
*MandatoryLiteralIdx == Component::DST_NUM + SrcIdx;
}
};

enum ComponentKind : unsigned {
SINGLE = 0, // A single VOP1 or VOP2 instruction which may be used in VOPD.
COMPONENT_X, // A VOPD instruction, X component.
Expand All @@ -546,7 +580,7 @@ class ComponentLayout {
// dstX, dstY, src0X [, other OpX operands], src0Y [, other OpY operands]
// Each ComponentKind has operand indices defined below.
static constexpr unsigned MC_DST_IDX[] = {0, 0, 1};
static constexpr unsigned FIRST_MC_SRC_IDX[] = {1, 2, 2 /* + OpXSrcNum */};
static constexpr unsigned FIRST_MC_SRC_IDX[] = {1, 2, 2 /* + OpX.SrcNum */};

// Parsed operands of regular instructions are ordered as follows:
// Mnemo dst src0 [vsrc1 ...]
Expand All @@ -555,81 +589,58 @@ class ComponentLayout {
// OpYMnemo dstY src0Y [vsrc1Y|imm vsrc1Y|vsrc1Y imm]
// Each ComponentKind has operand indices defined below.
static constexpr unsigned PARSED_DST_IDX[] = {1, 1,
4 /* + ParsedOpXSrcNum */};
4 /* + OpX.ParsedSrcNum */};
static constexpr unsigned FIRST_PARSED_SRC_IDX[] = {
2, 2, 5 /* + ParsedOpXSrcNum */};
2, 2, 5 /* + OpX.ParsedSrcNum */};

private:
ComponentKind Kind;
unsigned OpXSrcNum;
unsigned ParsedOpXSrcNum;
const ComponentKind Kind;
const ComponentProps PrevOp;

public:
ComponentLayout(ComponentKind Kind = ComponentKind::SINGLE,
unsigned OpXSrcNum = 0, unsigned ParsedOpXSrcNum = 0)
: Kind(Kind), OpXSrcNum(OpXSrcNum), ParsedOpXSrcNum(ParsedOpXSrcNum) {
assert(Kind <= ComponentKind::MAX);
assert((Kind == ComponentKind::COMPONENT_Y) == (OpXSrcNum > 0));
// Create layout for COMPONENT_X or SINGLE component
ComponentLayout(ComponentKind Kind) : Kind(Kind) {
assert(Kind == ComponentKind::SINGLE || Kind == ComponentKind::COMPONENT_X);
}

// Create layout for COMPONENT_Y which depends on COMPONENT_X layout
ComponentLayout(const ComponentProps &OpXProps)
: Kind(ComponentKind::COMPONENT_Y), PrevOp(OpXProps) {}

public:
unsigned getDstIndex() const { return MC_DST_IDX[Kind]; }
unsigned getSrcIndex(unsigned SrcIdx) const {
assert(SrcIdx < Component::MAX_SRC_NUM);
return FIRST_MC_SRC_IDX[Kind] + OpXSrcNum + SrcIdx;
return FIRST_MC_SRC_IDX[Kind] + getPrevOpSrcNum() + SrcIdx;
}

unsigned getParsedDstIndex() const {
return PARSED_DST_IDX[Kind] + ParsedOpXSrcNum;
return PARSED_DST_IDX[Kind] + getPrevOpParsedSrcNum();
}
unsigned getParsedSrcIndex(unsigned SrcIdx, bool ComponentHasSrc2Acc) const {
unsigned getParsedSrcIndex(unsigned SrcIdx) const {
assert(SrcIdx < Component::MAX_SRC_NUM);
// FMAC and DOT2C have a src2 operand on the MCInst but
// not on the asm representation. src2 is tied to dst.
if (ComponentHasSrc2Acc && SrcIdx == (MAX_SRC_NUM - 1))
return getParsedDstIndex();
return FIRST_PARSED_SRC_IDX[Kind] + ParsedOpXSrcNum + SrcIdx;
return FIRST_PARSED_SRC_IDX[Kind] + getPrevOpParsedSrcNum() + SrcIdx;
}
};

// Properties of VOPD components.
class ComponentProps {
private:
unsigned SrcOperandsNum;
Optional<unsigned> MandatoryLiteralIdx;
bool HasSrc2Acc;

public:
ComponentProps(const MCInstrDesc &OpDesc);

unsigned getSrcOperandsNum() const { return SrcOperandsNum; }
bool hasMandatoryLiteral() const { return MandatoryLiteralIdx.has_value(); }
unsigned getMandatoryLiteralIndex() const {
assert(hasMandatoryLiteral());
return *MandatoryLiteralIdx;
}
bool hasRegularSrcOperand(unsigned SrcIdx) const {
assert(SrcIdx < Component::MAX_SRC_NUM);
return SrcOperandsNum > SrcIdx && !hasMandatoryLiteralAt(SrcIdx);
}
bool hasSrc2Acc() const { return HasSrc2Acc; }

private:
bool hasMandatoryLiteralAt(unsigned SrcIdx) const {
assert(SrcIdx < Component::MAX_SRC_NUM);
return hasMandatoryLiteral() &&
*MandatoryLiteralIdx == Component::DST_NUM + SrcIdx;
unsigned getPrevOpSrcNum() const { return PrevOp.getSrcOperandsNum(); }
unsigned getPrevOpParsedSrcNum() const {
return PrevOp.getParsedSrcOperandsNum();
}
};

// Layout and properties of VOPD components.
class ComponentInfo : public ComponentLayout, public ComponentProps {
public:
// Create ComponentInfo for COMPONENT_X or SINGLE component
ComponentInfo(const MCInstrDesc &OpDesc,
ComponentKind Kind = ComponentKind::SINGLE)
: ComponentLayout(Kind), ComponentProps(OpDesc) {}

// Create ComponentInfo for COMPONENT_Y which depends on COMPONENT_X layout
ComponentInfo(const MCInstrDesc &OpDesc,
ComponentKind Kind = ComponentKind::SINGLE,
unsigned OpXSrcNum = 0, unsigned ParsedOpXSrcNum = 0)
: ComponentLayout(Kind, OpXSrcNum, ParsedOpXSrcNum),
ComponentProps(OpDesc) {}
const ComponentProps &OpXProps)
: ComponentLayout(OpXProps), ComponentProps(OpDesc) {}

// Map MC operand index to parsed operand index.
// Return 0 if the specified operand does not exist.
Expand Down
2 changes: 1 addition & 1 deletion llvm/test/MC/AMDGPU/gfx11_asm_vopd_err.s
Expand Up @@ -266,7 +266,7 @@ v_dual_fmac_f32 v7, v1, v2 :: v_dual_fmamk_f32 v6, v2
v_dual_fmamk_f32 v6, v1, 0xaf123456, v3 :: v_dual_fmac_f32 v5, v2, v3
// GFX11: error: src2 operands must use different VGPR banks
// GFX11-NEXT:{{^}}v_dual_fmamk_f32 v6, v1, 0xaf123456, v3 :: v_dual_fmac_f32 v5, v2, v3
// GFX11-NEXT:{{^}} ^
// GFX11-NEXT:{{^}} ^

//===----------------------------------------------------------------------===//
// Check invalid VOPD syntax.
Expand Down

0 comments on commit e468b1b

Please sign in to comment.