[AMDGPU][MC] Support UC_VERSION_* constants. (#95618)

Our other tools support them, so we want them in LLVM
assembler/disassembler too.
This commit is contained in:
Ivan Kosarev
2024-06-18 17:44:14 +03:00
committed by GitHub
parent 8052e94946
commit 162386693f
12 changed files with 179 additions and 32 deletions

View File

@@ -140,7 +140,9 @@ class ImmOperand<ValueType type, string name = NAME, bit optional = 0,
let PrintMethod = printer;
}
def s16imm : ImmOperand<i16, "S16Imm", 0, "printU16ImmOperand">;
class S16ImmOperand : ImmOperand<i16, "S16Imm", 0, "printU16ImmOperand">;
def s16imm : S16ImmOperand;
def u16imm : ImmOperand<i16, "U16Imm", 0, "printU16ImmOperand">;
class ValuePredicatedOperand<CustomOperand op, string valuePredicate,

View File

@@ -1314,6 +1314,8 @@ class AMDGPUAsmParser : public MCTargetAsmParser {
/// }
private:
void createConstantSymbol(StringRef Id, int64_t Val);
bool ParseAsAbsoluteExpression(uint32_t &Ret);
bool OutOfRangeError(SMRange Range);
/// Calculate VGPR/SGPR blocks required for given target, reserved
@@ -1408,36 +1410,28 @@ public:
setAvailableFeatures(ComputeAvailableFeatures(getFeatureBits()));
{
// TODO: make those pre-defined variables read-only.
// Currently there is none suitable machinery in the core llvm-mc for this.
// MCSymbol::isRedefinable is intended for another purpose, and
// AsmParser::parseDirectiveSet() cannot be specialized for specific target.
AMDGPU::IsaVersion ISA = AMDGPU::getIsaVersion(getSTI().getCPU());
MCContext &Ctx = getContext();
if (ISA.Major >= 6 && isHsaAbi(getSTI())) {
MCSymbol *Sym =
Ctx.getOrCreateSymbol(Twine(".amdgcn.gfx_generation_number"));
Sym->setVariableValue(MCConstantExpr::create(ISA.Major, Ctx));
Sym = Ctx.getOrCreateSymbol(Twine(".amdgcn.gfx_generation_minor"));
Sym->setVariableValue(MCConstantExpr::create(ISA.Minor, Ctx));
Sym = Ctx.getOrCreateSymbol(Twine(".amdgcn.gfx_generation_stepping"));
Sym->setVariableValue(MCConstantExpr::create(ISA.Stepping, Ctx));
} else {
MCSymbol *Sym =
Ctx.getOrCreateSymbol(Twine(".option.machine_version_major"));
Sym->setVariableValue(MCConstantExpr::create(ISA.Major, Ctx));
Sym = Ctx.getOrCreateSymbol(Twine(".option.machine_version_minor"));
Sym->setVariableValue(MCConstantExpr::create(ISA.Minor, Ctx));
Sym = Ctx.getOrCreateSymbol(Twine(".option.machine_version_stepping"));
Sym->setVariableValue(MCConstantExpr::create(ISA.Stepping, Ctx));
}
if (ISA.Major >= 6 && isHsaAbi(getSTI())) {
initializeGprCountSymbol(IS_VGPR);
initializeGprCountSymbol(IS_SGPR);
} else
KernelScope.initialize(getContext());
AMDGPU::IsaVersion ISA = AMDGPU::getIsaVersion(getSTI().getCPU());
if (ISA.Major >= 6 && isHsaAbi(getSTI())) {
createConstantSymbol(".amdgcn.gfx_generation_number", ISA.Major);
createConstantSymbol(".amdgcn.gfx_generation_minor", ISA.Minor);
createConstantSymbol(".amdgcn.gfx_generation_stepping", ISA.Stepping);
} else {
createConstantSymbol(".option.machine_version_major", ISA.Major);
createConstantSymbol(".option.machine_version_minor", ISA.Minor);
createConstantSymbol(".option.machine_version_stepping", ISA.Stepping);
}
if (ISA.Major >= 6 && isHsaAbi(getSTI())) {
initializeGprCountSymbol(IS_VGPR);
initializeGprCountSymbol(IS_SGPR);
} else
KernelScope.initialize(getContext());
for (auto [Symbol, Code] : AMDGPU::UCVersion::getGFXVersions())
createConstantSymbol(Symbol, Code);
createConstantSymbol("UC_VERSION_W64_BIT", 0x2000);
createConstantSymbol("UC_VERSION_W32_BIT", 0x4000);
createConstantSymbol("UC_VERSION_MDP_BIT", 0x8000);
}
bool hasMIMG_R128() const {
@@ -2486,6 +2480,16 @@ bool AMDGPUOperand::isInlineValue() const {
// AsmParser
//===----------------------------------------------------------------------===//
void AMDGPUAsmParser::createConstantSymbol(StringRef Id, int64_t Val) {
// TODO: make those pre-defined variables read-only.
// Currently there is none suitable machinery in the core llvm-mc for this.
// MCSymbol::isRedefinable is intended for another purpose, and
// AsmParser::parseDirectiveSet() cannot be specialized for specific target.
MCContext &Ctx = getContext();
MCSymbol *Sym = Ctx.getOrCreateSymbol(Id);
Sym->setVariableValue(MCConstantExpr::create(Val, Ctx));
}
static int getRegClass(RegisterKind Is, unsigned RegWidth) {
if (Is == IS_VGPR) {
switch (RegWidth) {

View File

@@ -21,6 +21,7 @@
#include "SIDefines.h"
#include "SIRegisterInfo.h"
#include "TargetInfo/AMDGPUTargetInfo.h"
#include "Utils/AMDGPUAsmUtils.h"
#include "Utils/AMDGPUBaseInfo.h"
#include "llvm-c/DisassemblerTypes.h"
#include "llvm/BinaryFormat/ELF.h"
@@ -52,6 +53,13 @@ AMDGPUDisassembler::AMDGPUDisassembler(const MCSubtargetInfo &STI,
// ToDo: AMDGPUDisassembler supports only VI ISA.
if (!STI.hasFeature(AMDGPU::FeatureGCN3Encoding) && !isGFX10Plus())
report_fatal_error("Disassembly not yet supported for subtarget");
for (auto [Symbol, Code] : AMDGPU::UCVersion::getGFXVersions())
createConstantSymbolExpr(Symbol, Code);
UCVersionW64Expr = createConstantSymbolExpr("UC_VERSION_W64_BIT", 0x2000);
UCVersionW32Expr = createConstantSymbolExpr("UC_VERSION_W32_BIT", 0x4000);
UCVersionMDPExpr = createConstantSymbolExpr("UC_VERSION_MDP_BIT", 0x8000);
}
void AMDGPUDisassembler::setABIVersion(unsigned Version) {
@@ -421,6 +429,13 @@ DECODE_SDWA(Src32)
DECODE_SDWA(Src16)
DECODE_SDWA(VopcDst)
static DecodeStatus decodeVersionImm(MCInst &Inst, unsigned Imm,
uint64_t /* Addr */,
const MCDisassembler *Decoder) {
auto DAsm = static_cast<const AMDGPUDisassembler *>(Decoder);
return addOperand(Inst, DAsm->decodeVersionImm(Imm));
}
#include "AMDGPUGenDisassemblerTables.inc"
//===----------------------------------------------------------------------===//
@@ -1727,6 +1742,41 @@ MCOperand AMDGPUDisassembler::decodeDpp8FI(unsigned Val) const {
return MCOperand::createImm(Val);
}
MCOperand AMDGPUDisassembler::decodeVersionImm(unsigned Imm) const {
using VersionField = AMDGPU::EncodingField<7, 0>;
using W64Bit = AMDGPU::EncodingBit<13>;
using W32Bit = AMDGPU::EncodingBit<14>;
using MDPBit = AMDGPU::EncodingBit<15>;
using Encoding = AMDGPU::EncodingFields<VersionField, W64Bit, W32Bit, MDPBit>;
auto [Version, W64, W32, MDP] = Encoding::decode(Imm);
// Decode into a plain immediate if any unused bits are raised.
if (Encoding::encode(Version, W64, W32, MDP) != Imm)
return MCOperand::createImm(Imm);
const auto &Versions = AMDGPU::UCVersion::getGFXVersions();
auto I = find_if(Versions,
[Version = Version](const AMDGPU::UCVersion::GFXVersion &V) {
return V.Code == Version;
});
MCContext &Ctx = getContext();
const MCExpr *E;
if (I == Versions.end())
E = MCConstantExpr::create(Version, Ctx);
else
E = MCSymbolRefExpr::create(Ctx.getOrCreateSymbol(I->Symbol), Ctx);
if (W64)
E = MCBinaryExpr::createOr(E, UCVersionW64Expr, Ctx);
if (W32)
E = MCBinaryExpr::createOr(E, UCVersionW32Expr, Ctx);
if (MDP)
E = MCBinaryExpr::createOr(E, UCVersionMDPExpr, Ctx);
return MCOperand::createExpr(E);
}
bool AMDGPUDisassembler::isVI() const {
return STI.hasFeature(AMDGPU::FeatureVolcanicIslands);
}
@@ -2312,6 +2362,15 @@ Expected<bool> AMDGPUDisassembler::onSymbolStart(SymbolInfoTy &Symbol,
return false;
}
const MCExpr *AMDGPUDisassembler::createConstantSymbolExpr(StringRef Id,
int64_t Val) {
MCContext &Ctx = getContext();
MCSymbol *Sym = Ctx.getOrCreateSymbol(Id);
assert(!Sym->isVariable());
Sym->setVariableValue(MCConstantExpr::create(Val, Ctx));
return MCSymbolRefExpr::create(Sym, Ctx);
}
//===----------------------------------------------------------------------===//
// AMDGPUSymbolizer
//===----------------------------------------------------------------------===//

View File

@@ -102,6 +102,11 @@ private:
mutable bool HasLiteral;
mutable std::optional<bool> EnableWavefrontSize32;
unsigned CodeObjectVersion;
const MCExpr *UCVersionW64Expr;
const MCExpr *UCVersionW32Expr;
const MCExpr *UCVersionMDPExpr;
const MCExpr *createConstantSymbolExpr(StringRef Id, int64_t Val);
public:
AMDGPUDisassembler(const MCSubtargetInfo &STI, MCContext &Ctx,
@@ -264,6 +269,8 @@ public:
MCOperand decodeSplitBarrier(unsigned Val) const;
MCOperand decodeDpp8FI(unsigned Val) const;
MCOperand decodeVersionImm(unsigned Imm) const;
int getTTmpIdx(unsigned Val) const;
const MCInstrInfo *getMCII() const { return MCII.get(); }

View File

@@ -56,9 +56,15 @@ void AMDGPUInstPrinter::printU4ImmOperand(const MCInst *MI, unsigned OpNo,
void AMDGPUInstPrinter::printU16ImmOperand(const MCInst *MI, unsigned OpNo,
const MCSubtargetInfo &STI,
raw_ostream &O) {
const MCOperand &Op = MI->getOperand(OpNo);
if (Op.isExpr()) {
Op.getExpr()->print(O, &MAI);
return;
}
// It's possible to end up with a 32-bit literal used with a 16-bit operand
// with ignored high bits. Print as 32-bit anyway in that case.
int64_t Imm = MI->getOperand(OpNo).getImm();
int64_t Imm = Op.getImm();
if (isInt<16>(Imm) || isUInt<16>(Imm))
O << formatHex(static_cast<uint64_t>(Imm & 0xffff));
else

View File

@@ -662,6 +662,11 @@ void AMDGPUMCCodeEmitter::getMachineOpValueT16Lo128(
void AMDGPUMCCodeEmitter::getMachineOpValueCommon(
const MCInst &MI, const MCOperand &MO, unsigned OpNo, APInt &Op,
SmallVectorImpl<MCFixup> &Fixups, const MCSubtargetInfo &STI) const {
int64_t Val;
if (MO.isExpr() && MO.getExpr()->evaluateAsAbsolute(Val)) {
Op = Val;
return;
}
if (MO.isExpr() && MO.getExpr()->getKind() != MCExpr::Constant) {
// FIXME: If this is expression is PCRel or not should not depend on what

View File

@@ -1196,11 +1196,15 @@ let SubtargetPredicate = isGFX9Plus in {
}
} // End SubtargetPredicate = isGFX9Plus
def VersionImm : S16ImmOperand {
let DecoderMethod = "decodeVersionImm";
}
let SubtargetPredicate = isGFX10Plus in {
def S_VERSION : SOPK_Pseudo<
"s_version",
(outs),
(ins s16imm:$simm16),
(ins VersionImm:$simm16),
"$simm16"> {
let has_sdst = 0;
}

View File

@@ -669,5 +669,20 @@ const char* const IdSymbolic[] = {
} // namespace VGPRIndexMode
namespace UCVersion {
ArrayRef<GFXVersion> getGFXVersions() {
// GFX6, GFX8 and GFX9 don't support s_version and there are no
// UC_VERSION_GFX* codes for them.
static const GFXVersion Versions[] = {{"UC_VERSION_GFX7", 0},
{"UC_VERSION_GFX10", 4},
{"UC_VERSION_GFX11", 6},
{"UC_VERSION_GFX12", 9}};
return Versions;
}
} // namespace UCVersion
} // namespace AMDGPU
} // namespace llvm

View File

@@ -116,6 +116,17 @@ extern const char* const IdSymbolic[];
} // namespace VGPRIndexMode
namespace UCVersion {
struct GFXVersion {
StringLiteral Symbol;
unsigned Code;
};
ArrayRef<GFXVersion> getGFXVersions();
} // namespace UCVersion
} // namespace AMDGPU
} // namespace llvm

View File

@@ -360,6 +360,10 @@ struct EncodingField {
static ValueType decode(uint64_t Encoded) { return Encoded; }
};
// Represents a single bit in an encoded value.
template <unsigned Bit, unsigned D = 0>
using EncodingBit = EncodingField<Bit, Bit, D>;
// A helper for encoding and decoding multiple fields.
template <typename... Fields> struct EncodingFields {
static constexpr uint64_t encode(Fields... Values) {

View File

@@ -30,6 +30,21 @@ s_version 0x1234
s_version 0xc1d1
// GFX12: encoding: [0xd1,0xc1,0x80,0xb0]
s_version UC_VERSION_GFX12
// GFX12: encoding: [0x09,0x00,0x80,0xb0]
s_version UC_VERSION_GFX12 | UC_VERSION_W32_BIT
// GFX12: encoding: [0x09,0x40,0x80,0xb0]
s_version UC_VERSION_GFX12 | UC_VERSION_W64_BIT
// GFX12: encoding: [0x09,0x20,0x80,0xb0]
s_version UC_VERSION_GFX12 | UC_VERSION_MDP_BIT
// GFX12: encoding: [0x09,0x80,0x80,0xb0]
s_version UC_VERSION_GFX12 | UC_VERSION_W64_BIT | UC_VERSION_MDP_BIT
// GFX12: encoding: [0x09,0xa0,0x80,0xb0]
s_cmovk_i32 s0, 0x1234
// GFX12: encoding: [0x34,0x12,0x00,0xb1]

View File

@@ -166,6 +166,21 @@
# GFX12: s_version 0xc1d1 ; encoding: [0xd1,0xc1,0x80,0xb0]
0xd1,0xc1,0x80,0xb0
# GFX12: s_version UC_VERSION_GFX12 ; encoding: [0x09,0x00,0x80,0xb0]
0x09,0x00,0x80,0xb0
# GFX12: s_version UC_VERSION_GFX12|UC_VERSION_W32_BIT ; encoding: [0x09,0x40,0x80,0xb0]
0x09,0x40,0x80,0xb0
# GFX12: s_version UC_VERSION_GFX12|UC_VERSION_W64_BIT ; encoding: [0x09,0x20,0x80,0xb0]
0x09,0x20,0x80,0xb0
# GFX12: s_version UC_VERSION_GFX12|UC_VERSION_MDP_BIT ; encoding: [0x09,0x80,0x80,0xb0]
0x09,0x80,0x80,0xb0
# GFX12: s_version ((128|UC_VERSION_W64_BIT)|UC_VERSION_W32_BIT)|UC_VERSION_MDP_BIT ; encoding: [0x80,0xe0,0x80,0xb0]
0x80,0xe0,0x80,0xb0
# GFX12: s_setreg_imm32_b32 hwreg(HW_REG_MODE), 0xaf123456 ; encoding: [0x01,0xf8,0x80,0xb9,0x56,0x34,0x12,0xaf]
0x01,0xf8,0x80,0xb9,0x56,0x34,0x12,0xaf