[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:
@@ -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,
|
||||
|
||||
@@ -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) {
|
||||
|
||||
@@ -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
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
@@ -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(); }
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
|
||||
@@ -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) {
|
||||
|
||||
@@ -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]
|
||||
|
||||
|
||||
@@ -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
|
||||
|
||||
|
||||
Reference in New Issue
Block a user