aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorIvan Kosarev <ivan.kosarev@amd.com>2024-06-18 17:44:14 +0300
committerGitHub <noreply@github.com>2024-06-18 15:44:14 +0100
commit162386693f663b3d0aa5403a45bfbc8edc3a84ed (patch)
tree822693e21a2b7be30c788e54081a39dabe1123f0
parent8052e94946ec7535f2d22aae1dbf3c48d3cd1b34 (diff)
downloadllvm-162386693f663b3d0aa5403a45bfbc8edc3a84ed.zip
llvm-162386693f663b3d0aa5403a45bfbc8edc3a84ed.tar.gz
llvm-162386693f663b3d0aa5403a45bfbc8edc3a84ed.tar.bz2
[AMDGPU][MC] Support UC_VERSION_* constants. (#95618)
Our other tools support them, so we want them in LLVM assembler/disassembler too.
-rw-r--r--llvm/lib/Target/AMDGPU/AMDGPUInstructions.td4
-rw-r--r--llvm/lib/Target/AMDGPU/AsmParser/AMDGPUAsmParser.cpp62
-rw-r--r--llvm/lib/Target/AMDGPU/Disassembler/AMDGPUDisassembler.cpp59
-rw-r--r--llvm/lib/Target/AMDGPU/Disassembler/AMDGPUDisassembler.h7
-rw-r--r--llvm/lib/Target/AMDGPU/MCTargetDesc/AMDGPUInstPrinter.cpp8
-rw-r--r--llvm/lib/Target/AMDGPU/MCTargetDesc/AMDGPUMCCodeEmitter.cpp5
-rw-r--r--llvm/lib/Target/AMDGPU/SOPInstructions.td6
-rw-r--r--llvm/lib/Target/AMDGPU/Utils/AMDGPUAsmUtils.cpp15
-rw-r--r--llvm/lib/Target/AMDGPU/Utils/AMDGPUAsmUtils.h11
-rw-r--r--llvm/lib/Target/AMDGPU/Utils/AMDGPUBaseInfo.h4
-rw-r--r--llvm/test/MC/AMDGPU/gfx12_asm_sopk.s15
-rw-r--r--llvm/test/MC/Disassembler/AMDGPU/gfx12_dasm_sopk.txt15
12 files changed, 179 insertions, 32 deletions
diff --git a/llvm/lib/Target/AMDGPU/AMDGPUInstructions.td b/llvm/lib/Target/AMDGPU/AMDGPUInstructions.td
index 65439f2..ebc6402 100644
--- a/llvm/lib/Target/AMDGPU/AMDGPUInstructions.td
+++ b/llvm/lib/Target/AMDGPU/AMDGPUInstructions.td
@@ -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,
diff --git a/llvm/lib/Target/AMDGPU/AsmParser/AMDGPUAsmParser.cpp b/llvm/lib/Target/AMDGPU/AsmParser/AMDGPUAsmParser.cpp
index bdb5a8d..8c7b33f 100644
--- a/llvm/lib/Target/AMDGPU/AsmParser/AMDGPUAsmParser.cpp
+++ b/llvm/lib/Target/AMDGPU/AsmParser/AMDGPUAsmParser.cpp
@@ -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) {
diff --git a/llvm/lib/Target/AMDGPU/Disassembler/AMDGPUDisassembler.cpp b/llvm/lib/Target/AMDGPU/Disassembler/AMDGPUDisassembler.cpp
index 05063c6c..76a559c 100644
--- a/llvm/lib/Target/AMDGPU/Disassembler/AMDGPUDisassembler.cpp
+++ b/llvm/lib/Target/AMDGPU/Disassembler/AMDGPUDisassembler.cpp
@@ -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
//===----------------------------------------------------------------------===//
diff --git a/llvm/lib/Target/AMDGPU/Disassembler/AMDGPUDisassembler.h b/llvm/lib/Target/AMDGPU/Disassembler/AMDGPUDisassembler.h
index 2061d83..694cd7a 100644
--- a/llvm/lib/Target/AMDGPU/Disassembler/AMDGPUDisassembler.h
+++ b/llvm/lib/Target/AMDGPU/Disassembler/AMDGPUDisassembler.h
@@ -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(); }
diff --git a/llvm/lib/Target/AMDGPU/MCTargetDesc/AMDGPUInstPrinter.cpp b/llvm/lib/Target/AMDGPU/MCTargetDesc/AMDGPUInstPrinter.cpp
index 227b738..bb5de36 100644
--- a/llvm/lib/Target/AMDGPU/MCTargetDesc/AMDGPUInstPrinter.cpp
+++ b/llvm/lib/Target/AMDGPU/MCTargetDesc/AMDGPUInstPrinter.cpp
@@ -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
diff --git a/llvm/lib/Target/AMDGPU/MCTargetDesc/AMDGPUMCCodeEmitter.cpp b/llvm/lib/Target/AMDGPU/MCTargetDesc/AMDGPUMCCodeEmitter.cpp
index fb93f45..b3cca91 100644
--- a/llvm/lib/Target/AMDGPU/MCTargetDesc/AMDGPUMCCodeEmitter.cpp
+++ b/llvm/lib/Target/AMDGPU/MCTargetDesc/AMDGPUMCCodeEmitter.cpp
@@ -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
diff --git a/llvm/lib/Target/AMDGPU/SOPInstructions.td b/llvm/lib/Target/AMDGPU/SOPInstructions.td
index aee5186..e1253d3e 100644
--- a/llvm/lib/Target/AMDGPU/SOPInstructions.td
+++ b/llvm/lib/Target/AMDGPU/SOPInstructions.td
@@ -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;
}
diff --git a/llvm/lib/Target/AMDGPU/Utils/AMDGPUAsmUtils.cpp b/llvm/lib/Target/AMDGPU/Utils/AMDGPUAsmUtils.cpp
index 2e1db16..3af536d 100644
--- a/llvm/lib/Target/AMDGPU/Utils/AMDGPUAsmUtils.cpp
+++ b/llvm/lib/Target/AMDGPU/Utils/AMDGPUAsmUtils.cpp
@@ -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
diff --git a/llvm/lib/Target/AMDGPU/Utils/AMDGPUAsmUtils.h b/llvm/lib/Target/AMDGPU/Utils/AMDGPUAsmUtils.h
index 069134a..c84c1a7 100644
--- a/llvm/lib/Target/AMDGPU/Utils/AMDGPUAsmUtils.h
+++ b/llvm/lib/Target/AMDGPU/Utils/AMDGPUAsmUtils.h
@@ -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
diff --git a/llvm/lib/Target/AMDGPU/Utils/AMDGPUBaseInfo.h b/llvm/lib/Target/AMDGPU/Utils/AMDGPUBaseInfo.h
index d4729b8..88b449c 100644
--- a/llvm/lib/Target/AMDGPU/Utils/AMDGPUBaseInfo.h
+++ b/llvm/lib/Target/AMDGPU/Utils/AMDGPUBaseInfo.h
@@ -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) {
diff --git a/llvm/test/MC/AMDGPU/gfx12_asm_sopk.s b/llvm/test/MC/AMDGPU/gfx12_asm_sopk.s
index 69566bb..5ce6847 100644
--- a/llvm/test/MC/AMDGPU/gfx12_asm_sopk.s
+++ b/llvm/test/MC/AMDGPU/gfx12_asm_sopk.s
@@ -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]
diff --git a/llvm/test/MC/Disassembler/AMDGPU/gfx12_dasm_sopk.txt b/llvm/test/MC/Disassembler/AMDGPU/gfx12_dasm_sopk.txt
index f2b9858..1d56c7b 100644
--- a/llvm/test/MC/Disassembler/AMDGPU/gfx12_dasm_sopk.txt
+++ b/llvm/test/MC/Disassembler/AMDGPU/gfx12_dasm_sopk.txt
@@ -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