Skip to content

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

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 2 commits into from
Jun 18, 2024
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
4 changes: 3 additions & 1 deletion llvm/lib/Target/AMDGPU/AMDGPUInstructions.td
Original file line number Diff line number Diff line change
Expand Up @@ -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,
Expand Down
62 changes: 33 additions & 29 deletions llvm/lib/Target/AMDGPU/AsmParser/AMDGPUAsmParser.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down Expand Up @@ -1408,36 +1410,28 @@ class AMDGPUAsmParser : public MCTargetAsmParser {

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 {
Expand Down Expand Up @@ -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) {
Expand Down
59 changes: 59 additions & 0 deletions llvm/lib/Target/AMDGPU/Disassembler/AMDGPUDisassembler.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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"
Expand Down Expand Up @@ -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) {
Expand Down Expand Up @@ -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"

//===----------------------------------------------------------------------===//
Expand Down Expand Up @@ -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);
}
Expand Down Expand Up @@ -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
//===----------------------------------------------------------------------===//
Expand Down
7 changes: 7 additions & 0 deletions llvm/lib/Target/AMDGPU/Disassembler/AMDGPUDisassembler.h
Original file line number Diff line number Diff line change
Expand Up @@ -102,6 +102,11 @@ class AMDGPUDisassembler : public MCDisassembler {
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,
Expand Down Expand Up @@ -264,6 +269,8 @@ class AMDGPUDisassembler : public MCDisassembler {
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(); }
Expand Down
8 changes: 7 additions & 1 deletion llvm/lib/Target/AMDGPU/MCTargetDesc/AMDGPUInstPrinter.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
5 changes: 5 additions & 0 deletions llvm/lib/Target/AMDGPU/MCTargetDesc/AMDGPUMCCodeEmitter.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
6 changes: 5 additions & 1 deletion llvm/lib/Target/AMDGPU/SOPInstructions.td
Original file line number Diff line number Diff line change
Expand Up @@ -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;
}
Expand Down
15 changes: 15 additions & 0 deletions llvm/lib/Target/AMDGPU/Utils/AMDGPUAsmUtils.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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},
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why is this missing 6, 8, and 9?

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

According to SP3, they don't support s_version and there are no UC_VERSION_GFX* codes for them.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can you add a comment for this

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Done.

{"UC_VERSION_GFX10", 4},
{"UC_VERSION_GFX11", 6},
{"UC_VERSION_GFX12", 9}};

return Versions;
}

} // namespace UCVersion

} // namespace AMDGPU
} // namespace llvm
11 changes: 11 additions & 0 deletions llvm/lib/Target/AMDGPU/Utils/AMDGPUAsmUtils.h
Original file line number Diff line number Diff line change
Expand Up @@ -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

Expand Down
4 changes: 4 additions & 0 deletions llvm/lib/Target/AMDGPU/Utils/AMDGPUBaseInfo.h
Original file line number Diff line number Diff line change
Expand Up @@ -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) {
Expand Down
15 changes: 15 additions & 0 deletions llvm/test/MC/AMDGPU/gfx12_asm_sopk.s
Original file line number Diff line number Diff line change
Expand Up @@ -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]

Expand Down
15 changes: 15 additions & 0 deletions llvm/test/MC/Disassembler/AMDGPU/gfx12_dasm_sopk.txt
Original file line number Diff line number Diff line change
Expand Up @@ -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

Expand Down
Loading