Skip to content

Commit 1623866

Browse files
authored
[AMDGPU][MC] Support UC_VERSION_* constants. (#95618)
Our other tools support them, so we want them in LLVM assembler/disassembler too.
1 parent 8052e94 commit 1623866

12 files changed

+179
-32
lines changed

llvm/lib/Target/AMDGPU/AMDGPUInstructions.td

+3-1
Original file line numberDiff line numberDiff line change
@@ -140,7 +140,9 @@ class ImmOperand<ValueType type, string name = NAME, bit optional = 0,
140140
let PrintMethod = printer;
141141
}
142142

143-
def s16imm : ImmOperand<i16, "S16Imm", 0, "printU16ImmOperand">;
143+
class S16ImmOperand : ImmOperand<i16, "S16Imm", 0, "printU16ImmOperand">;
144+
145+
def s16imm : S16ImmOperand;
144146
def u16imm : ImmOperand<i16, "U16Imm", 0, "printU16ImmOperand">;
145147

146148
class ValuePredicatedOperand<CustomOperand op, string valuePredicate,

llvm/lib/Target/AMDGPU/AsmParser/AMDGPUAsmParser.cpp

+33-29
Original file line numberDiff line numberDiff line change
@@ -1314,6 +1314,8 @@ class AMDGPUAsmParser : public MCTargetAsmParser {
13141314
/// }
13151315

13161316
private:
1317+
void createConstantSymbol(StringRef Id, int64_t Val);
1318+
13171319
bool ParseAsAbsoluteExpression(uint32_t &Ret);
13181320
bool OutOfRangeError(SMRange Range);
13191321
/// Calculate VGPR/SGPR blocks required for given target, reserved
@@ -1408,36 +1410,28 @@ class AMDGPUAsmParser : public MCTargetAsmParser {
14081410

14091411
setAvailableFeatures(ComputeAvailableFeatures(getFeatureBits()));
14101412

1411-
{
1412-
// TODO: make those pre-defined variables read-only.
1413-
// Currently there is none suitable machinery in the core llvm-mc for this.
1414-
// MCSymbol::isRedefinable is intended for another purpose, and
1415-
// AsmParser::parseDirectiveSet() cannot be specialized for specific target.
1416-
AMDGPU::IsaVersion ISA = AMDGPU::getIsaVersion(getSTI().getCPU());
1417-
MCContext &Ctx = getContext();
1418-
if (ISA.Major >= 6 && isHsaAbi(getSTI())) {
1419-
MCSymbol *Sym =
1420-
Ctx.getOrCreateSymbol(Twine(".amdgcn.gfx_generation_number"));
1421-
Sym->setVariableValue(MCConstantExpr::create(ISA.Major, Ctx));
1422-
Sym = Ctx.getOrCreateSymbol(Twine(".amdgcn.gfx_generation_minor"));
1423-
Sym->setVariableValue(MCConstantExpr::create(ISA.Minor, Ctx));
1424-
Sym = Ctx.getOrCreateSymbol(Twine(".amdgcn.gfx_generation_stepping"));
1425-
Sym->setVariableValue(MCConstantExpr::create(ISA.Stepping, Ctx));
1426-
} else {
1427-
MCSymbol *Sym =
1428-
Ctx.getOrCreateSymbol(Twine(".option.machine_version_major"));
1429-
Sym->setVariableValue(MCConstantExpr::create(ISA.Major, Ctx));
1430-
Sym = Ctx.getOrCreateSymbol(Twine(".option.machine_version_minor"));
1431-
Sym->setVariableValue(MCConstantExpr::create(ISA.Minor, Ctx));
1432-
Sym = Ctx.getOrCreateSymbol(Twine(".option.machine_version_stepping"));
1433-
Sym->setVariableValue(MCConstantExpr::create(ISA.Stepping, Ctx));
1434-
}
1435-
if (ISA.Major >= 6 && isHsaAbi(getSTI())) {
1436-
initializeGprCountSymbol(IS_VGPR);
1437-
initializeGprCountSymbol(IS_SGPR);
1438-
} else
1439-
KernelScope.initialize(getContext());
1413+
AMDGPU::IsaVersion ISA = AMDGPU::getIsaVersion(getSTI().getCPU());
1414+
if (ISA.Major >= 6 && isHsaAbi(getSTI())) {
1415+
createConstantSymbol(".amdgcn.gfx_generation_number", ISA.Major);
1416+
createConstantSymbol(".amdgcn.gfx_generation_minor", ISA.Minor);
1417+
createConstantSymbol(".amdgcn.gfx_generation_stepping", ISA.Stepping);
1418+
} else {
1419+
createConstantSymbol(".option.machine_version_major", ISA.Major);
1420+
createConstantSymbol(".option.machine_version_minor", ISA.Minor);
1421+
createConstantSymbol(".option.machine_version_stepping", ISA.Stepping);
14401422
}
1423+
if (ISA.Major >= 6 && isHsaAbi(getSTI())) {
1424+
initializeGprCountSymbol(IS_VGPR);
1425+
initializeGprCountSymbol(IS_SGPR);
1426+
} else
1427+
KernelScope.initialize(getContext());
1428+
1429+
for (auto [Symbol, Code] : AMDGPU::UCVersion::getGFXVersions())
1430+
createConstantSymbol(Symbol, Code);
1431+
1432+
createConstantSymbol("UC_VERSION_W64_BIT", 0x2000);
1433+
createConstantSymbol("UC_VERSION_W32_BIT", 0x4000);
1434+
createConstantSymbol("UC_VERSION_MDP_BIT", 0x8000);
14411435
}
14421436

14431437
bool hasMIMG_R128() const {
@@ -2486,6 +2480,16 @@ bool AMDGPUOperand::isInlineValue() const {
24862480
// AsmParser
24872481
//===----------------------------------------------------------------------===//
24882482

2483+
void AMDGPUAsmParser::createConstantSymbol(StringRef Id, int64_t Val) {
2484+
// TODO: make those pre-defined variables read-only.
2485+
// Currently there is none suitable machinery in the core llvm-mc for this.
2486+
// MCSymbol::isRedefinable is intended for another purpose, and
2487+
// AsmParser::parseDirectiveSet() cannot be specialized for specific target.
2488+
MCContext &Ctx = getContext();
2489+
MCSymbol *Sym = Ctx.getOrCreateSymbol(Id);
2490+
Sym->setVariableValue(MCConstantExpr::create(Val, Ctx));
2491+
}
2492+
24892493
static int getRegClass(RegisterKind Is, unsigned RegWidth) {
24902494
if (Is == IS_VGPR) {
24912495
switch (RegWidth) {

llvm/lib/Target/AMDGPU/Disassembler/AMDGPUDisassembler.cpp

+59
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@
2121
#include "SIDefines.h"
2222
#include "SIRegisterInfo.h"
2323
#include "TargetInfo/AMDGPUTargetInfo.h"
24+
#include "Utils/AMDGPUAsmUtils.h"
2425
#include "Utils/AMDGPUBaseInfo.h"
2526
#include "llvm-c/DisassemblerTypes.h"
2627
#include "llvm/BinaryFormat/ELF.h"
@@ -52,6 +53,13 @@ AMDGPUDisassembler::AMDGPUDisassembler(const MCSubtargetInfo &STI,
5253
// ToDo: AMDGPUDisassembler supports only VI ISA.
5354
if (!STI.hasFeature(AMDGPU::FeatureGCN3Encoding) && !isGFX10Plus())
5455
report_fatal_error("Disassembly not yet supported for subtarget");
56+
57+
for (auto [Symbol, Code] : AMDGPU::UCVersion::getGFXVersions())
58+
createConstantSymbolExpr(Symbol, Code);
59+
60+
UCVersionW64Expr = createConstantSymbolExpr("UC_VERSION_W64_BIT", 0x2000);
61+
UCVersionW32Expr = createConstantSymbolExpr("UC_VERSION_W32_BIT", 0x4000);
62+
UCVersionMDPExpr = createConstantSymbolExpr("UC_VERSION_MDP_BIT", 0x8000);
5563
}
5664

5765
void AMDGPUDisassembler::setABIVersion(unsigned Version) {
@@ -421,6 +429,13 @@ DECODE_SDWA(Src32)
421429
DECODE_SDWA(Src16)
422430
DECODE_SDWA(VopcDst)
423431

432+
static DecodeStatus decodeVersionImm(MCInst &Inst, unsigned Imm,
433+
uint64_t /* Addr */,
434+
const MCDisassembler *Decoder) {
435+
auto DAsm = static_cast<const AMDGPUDisassembler *>(Decoder);
436+
return addOperand(Inst, DAsm->decodeVersionImm(Imm));
437+
}
438+
424439
#include "AMDGPUGenDisassemblerTables.inc"
425440

426441
//===----------------------------------------------------------------------===//
@@ -1727,6 +1742,41 @@ MCOperand AMDGPUDisassembler::decodeDpp8FI(unsigned Val) const {
17271742
return MCOperand::createImm(Val);
17281743
}
17291744

1745+
MCOperand AMDGPUDisassembler::decodeVersionImm(unsigned Imm) const {
1746+
using VersionField = AMDGPU::EncodingField<7, 0>;
1747+
using W64Bit = AMDGPU::EncodingBit<13>;
1748+
using W32Bit = AMDGPU::EncodingBit<14>;
1749+
using MDPBit = AMDGPU::EncodingBit<15>;
1750+
using Encoding = AMDGPU::EncodingFields<VersionField, W64Bit, W32Bit, MDPBit>;
1751+
1752+
auto [Version, W64, W32, MDP] = Encoding::decode(Imm);
1753+
1754+
// Decode into a plain immediate if any unused bits are raised.
1755+
if (Encoding::encode(Version, W64, W32, MDP) != Imm)
1756+
return MCOperand::createImm(Imm);
1757+
1758+
const auto &Versions = AMDGPU::UCVersion::getGFXVersions();
1759+
auto I = find_if(Versions,
1760+
[Version = Version](const AMDGPU::UCVersion::GFXVersion &V) {
1761+
return V.Code == Version;
1762+
});
1763+
MCContext &Ctx = getContext();
1764+
const MCExpr *E;
1765+
if (I == Versions.end())
1766+
E = MCConstantExpr::create(Version, Ctx);
1767+
else
1768+
E = MCSymbolRefExpr::create(Ctx.getOrCreateSymbol(I->Symbol), Ctx);
1769+
1770+
if (W64)
1771+
E = MCBinaryExpr::createOr(E, UCVersionW64Expr, Ctx);
1772+
if (W32)
1773+
E = MCBinaryExpr::createOr(E, UCVersionW32Expr, Ctx);
1774+
if (MDP)
1775+
E = MCBinaryExpr::createOr(E, UCVersionMDPExpr, Ctx);
1776+
1777+
return MCOperand::createExpr(E);
1778+
}
1779+
17301780
bool AMDGPUDisassembler::isVI() const {
17311781
return STI.hasFeature(AMDGPU::FeatureVolcanicIslands);
17321782
}
@@ -2312,6 +2362,15 @@ Expected<bool> AMDGPUDisassembler::onSymbolStart(SymbolInfoTy &Symbol,
23122362
return false;
23132363
}
23142364

2365+
const MCExpr *AMDGPUDisassembler::createConstantSymbolExpr(StringRef Id,
2366+
int64_t Val) {
2367+
MCContext &Ctx = getContext();
2368+
MCSymbol *Sym = Ctx.getOrCreateSymbol(Id);
2369+
assert(!Sym->isVariable());
2370+
Sym->setVariableValue(MCConstantExpr::create(Val, Ctx));
2371+
return MCSymbolRefExpr::create(Sym, Ctx);
2372+
}
2373+
23152374
//===----------------------------------------------------------------------===//
23162375
// AMDGPUSymbolizer
23172376
//===----------------------------------------------------------------------===//

llvm/lib/Target/AMDGPU/Disassembler/AMDGPUDisassembler.h

+7
Original file line numberDiff line numberDiff line change
@@ -102,6 +102,11 @@ class AMDGPUDisassembler : public MCDisassembler {
102102
mutable bool HasLiteral;
103103
mutable std::optional<bool> EnableWavefrontSize32;
104104
unsigned CodeObjectVersion;
105+
const MCExpr *UCVersionW64Expr;
106+
const MCExpr *UCVersionW32Expr;
107+
const MCExpr *UCVersionMDPExpr;
108+
109+
const MCExpr *createConstantSymbolExpr(StringRef Id, int64_t Val);
105110

106111
public:
107112
AMDGPUDisassembler(const MCSubtargetInfo &STI, MCContext &Ctx,
@@ -264,6 +269,8 @@ class AMDGPUDisassembler : public MCDisassembler {
264269
MCOperand decodeSplitBarrier(unsigned Val) const;
265270
MCOperand decodeDpp8FI(unsigned Val) const;
266271

272+
MCOperand decodeVersionImm(unsigned Imm) const;
273+
267274
int getTTmpIdx(unsigned Val) const;
268275

269276
const MCInstrInfo *getMCII() const { return MCII.get(); }

llvm/lib/Target/AMDGPU/MCTargetDesc/AMDGPUInstPrinter.cpp

+7-1
Original file line numberDiff line numberDiff line change
@@ -56,9 +56,15 @@ void AMDGPUInstPrinter::printU4ImmOperand(const MCInst *MI, unsigned OpNo,
5656
void AMDGPUInstPrinter::printU16ImmOperand(const MCInst *MI, unsigned OpNo,
5757
const MCSubtargetInfo &STI,
5858
raw_ostream &O) {
59+
const MCOperand &Op = MI->getOperand(OpNo);
60+
if (Op.isExpr()) {
61+
Op.getExpr()->print(O, &MAI);
62+
return;
63+
}
64+
5965
// It's possible to end up with a 32-bit literal used with a 16-bit operand
6066
// with ignored high bits. Print as 32-bit anyway in that case.
61-
int64_t Imm = MI->getOperand(OpNo).getImm();
67+
int64_t Imm = Op.getImm();
6268
if (isInt<16>(Imm) || isUInt<16>(Imm))
6369
O << formatHex(static_cast<uint64_t>(Imm & 0xffff));
6470
else

llvm/lib/Target/AMDGPU/MCTargetDesc/AMDGPUMCCodeEmitter.cpp

+5
Original file line numberDiff line numberDiff line change
@@ -662,6 +662,11 @@ void AMDGPUMCCodeEmitter::getMachineOpValueT16Lo128(
662662
void AMDGPUMCCodeEmitter::getMachineOpValueCommon(
663663
const MCInst &MI, const MCOperand &MO, unsigned OpNo, APInt &Op,
664664
SmallVectorImpl<MCFixup> &Fixups, const MCSubtargetInfo &STI) const {
665+
int64_t Val;
666+
if (MO.isExpr() && MO.getExpr()->evaluateAsAbsolute(Val)) {
667+
Op = Val;
668+
return;
669+
}
665670

666671
if (MO.isExpr() && MO.getExpr()->getKind() != MCExpr::Constant) {
667672
// FIXME: If this is expression is PCRel or not should not depend on what

llvm/lib/Target/AMDGPU/SOPInstructions.td

+5-1
Original file line numberDiff line numberDiff line change
@@ -1196,11 +1196,15 @@ let SubtargetPredicate = isGFX9Plus in {
11961196
}
11971197
} // End SubtargetPredicate = isGFX9Plus
11981198

1199+
def VersionImm : S16ImmOperand {
1200+
let DecoderMethod = "decodeVersionImm";
1201+
}
1202+
11991203
let SubtargetPredicate = isGFX10Plus in {
12001204
def S_VERSION : SOPK_Pseudo<
12011205
"s_version",
12021206
(outs),
1203-
(ins s16imm:$simm16),
1207+
(ins VersionImm:$simm16),
12041208
"$simm16"> {
12051209
let has_sdst = 0;
12061210
}

llvm/lib/Target/AMDGPU/Utils/AMDGPUAsmUtils.cpp

+15
Original file line numberDiff line numberDiff line change
@@ -669,5 +669,20 @@ const char* const IdSymbolic[] = {
669669

670670
} // namespace VGPRIndexMode
671671

672+
namespace UCVersion {
673+
674+
ArrayRef<GFXVersion> getGFXVersions() {
675+
// GFX6, GFX8 and GFX9 don't support s_version and there are no
676+
// UC_VERSION_GFX* codes for them.
677+
static const GFXVersion Versions[] = {{"UC_VERSION_GFX7", 0},
678+
{"UC_VERSION_GFX10", 4},
679+
{"UC_VERSION_GFX11", 6},
680+
{"UC_VERSION_GFX12", 9}};
681+
682+
return Versions;
683+
}
684+
685+
} // namespace UCVersion
686+
672687
} // namespace AMDGPU
673688
} // namespace llvm

llvm/lib/Target/AMDGPU/Utils/AMDGPUAsmUtils.h

+11
Original file line numberDiff line numberDiff line change
@@ -116,6 +116,17 @@ extern const char* const IdSymbolic[];
116116

117117
} // namespace VGPRIndexMode
118118

119+
namespace UCVersion {
120+
121+
struct GFXVersion {
122+
StringLiteral Symbol;
123+
unsigned Code;
124+
};
125+
126+
ArrayRef<GFXVersion> getGFXVersions();
127+
128+
} // namespace UCVersion
129+
119130
} // namespace AMDGPU
120131
} // namespace llvm
121132

llvm/lib/Target/AMDGPU/Utils/AMDGPUBaseInfo.h

+4
Original file line numberDiff line numberDiff line change
@@ -360,6 +360,10 @@ struct EncodingField {
360360
static ValueType decode(uint64_t Encoded) { return Encoded; }
361361
};
362362

363+
// Represents a single bit in an encoded value.
364+
template <unsigned Bit, unsigned D = 0>
365+
using EncodingBit = EncodingField<Bit, Bit, D>;
366+
363367
// A helper for encoding and decoding multiple fields.
364368
template <typename... Fields> struct EncodingFields {
365369
static constexpr uint64_t encode(Fields... Values) {

llvm/test/MC/AMDGPU/gfx12_asm_sopk.s

+15
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,21 @@ s_version 0x1234
3030
s_version 0xc1d1
3131
// GFX12: encoding: [0xd1,0xc1,0x80,0xb0]
3232

33+
s_version UC_VERSION_GFX12
34+
// GFX12: encoding: [0x09,0x00,0x80,0xb0]
35+
36+
s_version UC_VERSION_GFX12 | UC_VERSION_W32_BIT
37+
// GFX12: encoding: [0x09,0x40,0x80,0xb0]
38+
39+
s_version UC_VERSION_GFX12 | UC_VERSION_W64_BIT
40+
// GFX12: encoding: [0x09,0x20,0x80,0xb0]
41+
42+
s_version UC_VERSION_GFX12 | UC_VERSION_MDP_BIT
43+
// GFX12: encoding: [0x09,0x80,0x80,0xb0]
44+
45+
s_version UC_VERSION_GFX12 | UC_VERSION_W64_BIT | UC_VERSION_MDP_BIT
46+
// GFX12: encoding: [0x09,0xa0,0x80,0xb0]
47+
3348
s_cmovk_i32 s0, 0x1234
3449
// GFX12: encoding: [0x34,0x12,0x00,0xb1]
3550

llvm/test/MC/Disassembler/AMDGPU/gfx12_dasm_sopk.txt

+15
Original file line numberDiff line numberDiff line change
@@ -166,6 +166,21 @@
166166
# GFX12: s_version 0xc1d1 ; encoding: [0xd1,0xc1,0x80,0xb0]
167167
0xd1,0xc1,0x80,0xb0
168168

169+
# GFX12: s_version UC_VERSION_GFX12 ; encoding: [0x09,0x00,0x80,0xb0]
170+
0x09,0x00,0x80,0xb0
171+
172+
# GFX12: s_version UC_VERSION_GFX12|UC_VERSION_W32_BIT ; encoding: [0x09,0x40,0x80,0xb0]
173+
0x09,0x40,0x80,0xb0
174+
175+
# GFX12: s_version UC_VERSION_GFX12|UC_VERSION_W64_BIT ; encoding: [0x09,0x20,0x80,0xb0]
176+
0x09,0x20,0x80,0xb0
177+
178+
# GFX12: s_version UC_VERSION_GFX12|UC_VERSION_MDP_BIT ; encoding: [0x09,0x80,0x80,0xb0]
179+
0x09,0x80,0x80,0xb0
180+
181+
# GFX12: s_version ((128|UC_VERSION_W64_BIT)|UC_VERSION_W32_BIT)|UC_VERSION_MDP_BIT ; encoding: [0x80,0xe0,0x80,0xb0]
182+
0x80,0xe0,0x80,0xb0
183+
169184
# GFX12: s_setreg_imm32_b32 hwreg(HW_REG_MODE), 0xaf123456 ; encoding: [0x01,0xf8,0x80,0xb9,0x56,0x34,0x12,0xaf]
170185
0x01,0xf8,0x80,0xb9,0x56,0x34,0x12,0xaf
171186

0 commit comments

Comments
 (0)