[llvm] e468b1b - [AMDGPU][GFX11] Refactor VOPD operands handling
Dmitry Preobrazhensky via llvm-commits
llvm-commits at lists.llvm.org
Wed Nov 16 05:29:34 PST 2022
Author: Dmitry Preobrazhensky
Date: 2022-11-16T16:29:12+03:00
New Revision: e468b1b740e522c212be24d2ead25383fe46f8f5
URL: https://github.com/llvm/llvm-project/commit/e468b1b740e522c212be24d2ead25383fe46f8f5
DIFF: https://github.com/llvm/llvm-project/commit/e468b1b740e522c212be24d2ead25383fe46f8f5.diff
LOG: [AMDGPU][GFX11] Refactor VOPD operands handling
Differential Revision: https://reviews.llvm.org/D137952
Added:
Modified:
llvm/lib/Target/AMDGPU/AsmParser/AMDGPUAsmParser.cpp
llvm/lib/Target/AMDGPU/Utils/AMDGPUBaseInfo.cpp
llvm/lib/Target/AMDGPU/Utils/AMDGPUBaseInfo.h
llvm/test/MC/AMDGPU/gfx11_asm_vopd_err.s
Removed:
################################################################################
diff --git a/llvm/lib/Target/AMDGPU/AsmParser/AMDGPUAsmParser.cpp b/llvm/lib/Target/AMDGPU/AsmParser/AMDGPUAsmParser.cpp
index 07d9b7b6fc7ad..f739ccad34852 100644
--- a/llvm/lib/Target/AMDGPU/AsmParser/AMDGPUAsmParser.cpp
+++ b/llvm/lib/Target/AMDGPU/AsmParser/AMDGPUAsmParser.cpp
@@ -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;
@@ -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());
}
}
diff --git a/llvm/lib/Target/AMDGPU/Utils/AMDGPUBaseInfo.cpp b/llvm/lib/Target/AMDGPU/Utils/AMDGPUBaseInfo.cpp
index 80e4dada6b36a..8a13567303f5e 100644
--- a/llvm/lib/Target/AMDGPU/Utils/AMDGPUBaseInfo.cpp
+++ b/llvm/lib/Target/AMDGPU/Utils/AMDGPUBaseInfo.cpp
@@ -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;
@@ -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
@@ -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);
}
diff --git a/llvm/lib/Target/AMDGPU/Utils/AMDGPUBaseInfo.h b/llvm/lib/Target/AMDGPU/Utils/AMDGPUBaseInfo.h
index 778987cb03e76..40b5b60212d42 100644
--- a/llvm/lib/Target/AMDGPU/Utils/AMDGPUBaseInfo.h
+++ b/llvm/lib/Target/AMDGPU/Utils/AMDGPUBaseInfo.h
@@ -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.
@@ -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 ...]
@@ -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.
diff --git a/llvm/test/MC/AMDGPU/gfx11_asm_vopd_err.s b/llvm/test/MC/AMDGPU/gfx11_asm_vopd_err.s
index bec22526bd124..f26fb6a4e2cda 100644
--- a/llvm/test/MC/AMDGPU/gfx11_asm_vopd_err.s
+++ b/llvm/test/MC/AMDGPU/gfx11_asm_vopd_err.s
@@ -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
diff erent 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.
More information about the llvm-commits
mailing list