Skip to content

Commit f090554

Browse files
authored
[AMDGPU] MC support for v_fmaak_f64/v_fmamk_f64 gfx1250 intructions (#148282)
1 parent 27ccb96 commit f090554

17 files changed

+481
-18
lines changed

llvm/lib/Target/AMDGPU/AMDGPU.td

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2488,6 +2488,10 @@ def HasFmaakFmamkF32Insts :
24882488
Predicate<"Subtarget->hasFmaakFmamkF32Insts()">,
24892489
AssemblerPredicate<(any_of FeatureGFX10Insts, FeatureGFX940Insts)>;
24902490

2491+
def HasFmaakFmamkF64Insts :
2492+
Predicate<"Subtarget->hasFmaakFmamkF64Insts()">,
2493+
AssemblerPredicate<(any_of FeatureGFX1250Insts)>;
2494+
24912495
def HasImageInsts : Predicate<"Subtarget->hasImageInsts()">,
24922496
AssemblerPredicate<(all_of FeatureImageInsts)>;
24932497

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

Lines changed: 24 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -951,6 +951,8 @@ class AMDGPUOperand : public MCParsedAsmOperand {
951951
return isLiteralImm(MVT::f16);
952952
}
953953

954+
bool isKImmFP64() const { return isLiteralImm(MVT::f64); }
955+
954956
bool isMem() const override {
955957
return false;
956958
}
@@ -2003,6 +2005,7 @@ static const fltSemantics *getOpFltSemantics(uint8_t OperandType) {
20032005
case AMDGPU::OPERAND_REG_INLINE_C_INT64:
20042006
case AMDGPU::OPERAND_REG_INLINE_C_FP64:
20052007
case AMDGPU::OPERAND_REG_INLINE_AC_FP64:
2008+
case AMDGPU::OPERAND_KIMM64:
20062009
return &APFloat::IEEEdouble();
20072010
case AMDGPU::OPERAND_REG_IMM_FP16:
20082011
case AMDGPU::OPERAND_REG_INLINE_C_FP16:
@@ -2343,6 +2346,11 @@ void AMDGPUOperand::addLiteralImmOperand(MCInst &Inst, int64_t Val, bool ApplyMo
23432346
// in predicate methods (isLiteralImm())
23442347
llvm_unreachable("fp literal in 64-bit integer instruction.");
23452348

2349+
case AMDGPU::OPERAND_KIMM64:
2350+
Inst.addOperand(MCOperand::createImm(Val));
2351+
setImmKindMandatoryLiteral();
2352+
return;
2353+
23462354
case AMDGPU::OPERAND_REG_IMM_BF16:
23472355
case AMDGPU::OPERAND_REG_INLINE_C_BF16:
23482356
case AMDGPU::OPERAND_REG_INLINE_C_V2BF16:
@@ -2548,6 +2556,13 @@ void AMDGPUOperand::addLiteralImmOperand(MCInst &Inst, int64_t Val, bool ApplyMo
25482556
Inst.addOperand(MCOperand::createImm(Literal.getLoBits(16).getZExtValue()));
25492557
setImmKindMandatoryLiteral();
25502558
return;
2559+
case AMDGPU::OPERAND_KIMM64:
2560+
if ((isInt<32>(Val) || isUInt<32>(Val)) && !getModifiers().Lit64)
2561+
Val <<= 32;
2562+
2563+
Inst.addOperand(MCOperand::createImm(Val));
2564+
setImmKindMandatoryLiteral();
2565+
return;
25512566
default:
25522567
llvm_unreachable("invalid operand size");
25532568
}
@@ -4992,7 +5007,7 @@ bool AMDGPUAsmParser::validateVOPLiteral(const MCInst &Inst,
49925007

49935008
unsigned NumExprs = 0;
49945009
unsigned NumLiterals = 0;
4995-
uint32_t LiteralValue;
5010+
uint64_t LiteralValue;
49965011

49975012
for (int OpIdx : OpIndices) {
49985013
if (OpIdx == -1)
@@ -5006,16 +5021,21 @@ bool AMDGPUAsmParser::validateVOPLiteral(const MCInst &Inst,
50065021

50075022
if (MO.isImm() && !isInlineConstant(Inst, OpIdx)) {
50085023
uint64_t Value = static_cast<uint64_t>(MO.getImm());
5009-
bool IsFP64 = AMDGPU::isSISrcFPOperand(Desc, OpIdx) &&
5024+
bool IsForcedFP64 =
5025+
Desc.operands()[OpIdx].OperandType == AMDGPU::OPERAND_KIMM64 ||
5026+
(Desc.operands()[OpIdx].OperandType == AMDGPU::OPERAND_REG_IMM_FP64 &&
5027+
HasMandatoryLiteral);
5028+
bool IsFP64 = (IsForcedFP64 || AMDGPU::isSISrcFPOperand(Desc, OpIdx)) &&
50105029
AMDGPU::getOperandSize(Desc.operands()[OpIdx]) == 8;
50115030
bool IsValid32Op = AMDGPU::isValid32BitLiteral(Value, IsFP64);
50125031

5013-
if (!IsValid32Op && !isInt<32>(Value) && !isUInt<32>(Value)) {
5032+
if (!IsValid32Op && !isInt<32>(Value) && !isUInt<32>(Value) &&
5033+
!IsForcedFP64 && (!has64BitLiterals() || Desc.getSize() != 4)) {
50145034
Error(getLitLoc(Operands), "invalid operand for instruction");
50155035
return false;
50165036
}
50175037

5018-
if (IsFP64 && IsValid32Op)
5038+
if (IsFP64 && IsValid32Op && !IsForcedFP64)
50195039
Value = Hi_32(Value);
50205040

50215041
if (NumLiterals == 0 || LiteralValue != Value) {

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

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -353,6 +353,13 @@ static DecodeStatus decodeOperand_KImmFP(MCInst &Inst, unsigned Imm,
353353
return addOperand(Inst, DAsm->decodeMandatoryLiteralConstant(Imm));
354354
}
355355

356+
static DecodeStatus decodeOperand_KImmFP64(MCInst &Inst, uint64_t Imm,
357+
uint64_t Addr,
358+
const MCDisassembler *Decoder) {
359+
const auto *DAsm = static_cast<const AMDGPUDisassembler *>(Decoder);
360+
return addOperand(Inst, DAsm->decodeMandatoryLiteral64Constant(Imm));
361+
}
362+
356363
static DecodeStatus decodeOperandVOPDDstY(MCInst &Inst, unsigned Val,
357364
uint64_t Addr, const void *Decoder) {
358365
const auto *DAsm = static_cast<const AMDGPUDisassembler *>(Decoder);
@@ -613,6 +620,15 @@ DecodeStatus AMDGPUDisassembler::getInstruction(MCInst &MI, uint64_t &Size,
613620
tryDecodeInst(DecoderTableGFX12W6496, MI, DecW, Address, CS))
614621
break;
615622

623+
if (STI.hasFeature(AMDGPU::Feature64BitLiterals)) {
624+
// Return 8 bytes for a potential literal.
625+
Bytes = Bytes_.slice(4, MaxInstBytesNum - 4);
626+
627+
if (isGFX1250() &&
628+
tryDecodeInst(DecoderTableGFX125096, MI, DecW, Address, CS))
629+
break;
630+
}
631+
616632
// Reinitialize Bytes
617633
Bytes = Bytes_.slice(0, MaxInstBytesNum);
618634

@@ -1467,6 +1483,17 @@ AMDGPUDisassembler::decodeMandatoryLiteralConstant(unsigned Val) const {
14671483
return MCOperand::createImm(Literal);
14681484
}
14691485

1486+
MCOperand
1487+
AMDGPUDisassembler::decodeMandatoryLiteral64Constant(uint64_t Val) const {
1488+
if (HasLiteral) {
1489+
if (Literal64 != Val)
1490+
return errOperand(Val, "More than one unique literal is illegal");
1491+
}
1492+
HasLiteral = true;
1493+
Literal = Literal64 = Val;
1494+
return MCOperand::createImm(Literal64);
1495+
}
1496+
14701497
MCOperand AMDGPUDisassembler::decodeLiteralConstant(bool ExtendFP64) const {
14711498
// For now all literal constants are supposed to be unsigned integer
14721499
// ToDo: deal with signed/unsigned 64-bit integer constants

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

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -178,6 +178,7 @@ class AMDGPUDisassembler : public MCDisassembler {
178178
static MCOperand decodeIntImmed(unsigned Imm);
179179

180180
MCOperand decodeMandatoryLiteralConstant(unsigned Imm) const;
181+
MCOperand decodeMandatoryLiteral64Constant(uint64_t Imm) const;
181182
MCOperand decodeLiteralConstant(bool ExtendFP64) const;
182183
MCOperand decodeLiteral64Constant() const;
183184

llvm/lib/Target/AMDGPU/GCNSubtarget.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1100,6 +1100,8 @@ class GCNSubtarget final : public AMDGPUGenSubtargetInfo,
11001100
return getGeneration() >= GFX10 || hasGFX940Insts();
11011101
}
11021102

1103+
bool hasFmaakFmamkF64Insts() const { return hasGFX1250Insts(); }
1104+
11031105
bool hasImageInsts() const {
11041106
return HasImageInsts;
11051107
}

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

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -76,6 +76,18 @@ void AMDGPUInstPrinter::printU32ImmOperand(const MCInst *MI, unsigned OpNo,
7676
O << formatHex(MI->getOperand(OpNo).getImm() & 0xffffffff);
7777
}
7878

79+
void AMDGPUInstPrinter::printFP64ImmOperand(const MCInst *MI, unsigned OpNo,
80+
const MCSubtargetInfo &STI,
81+
raw_ostream &O) {
82+
// KIMM64
83+
// This part needs to align with AMDGPUInstPrinter::printImmediate64.
84+
uint64_t Imm = MI->getOperand(OpNo).getImm();
85+
if (STI.hasFeature(AMDGPU::Feature64BitLiterals) && Lo_32(Imm))
86+
O << "lit64(" << formatHex(static_cast<uint64_t>(Imm)) << ')';
87+
else
88+
O << formatHex(static_cast<uint64_t>(Hi_32(Imm)));
89+
}
90+
7991
void AMDGPUInstPrinter::printNamedBit(const MCInst *MI, unsigned OpNo,
8092
raw_ostream &O, StringRef BitName) {
8193
if (MI->getOperand(OpNo).getImm()) {

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

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -42,6 +42,8 @@ class AMDGPUInstPrinter : public MCInstPrinter {
4242
void printU16ImmDecOperand(const MCInst *MI, unsigned OpNo, raw_ostream &O);
4343
void printU32ImmOperand(const MCInst *MI, unsigned OpNo,
4444
const MCSubtargetInfo &STI, raw_ostream &O);
45+
void printFP64ImmOperand(const MCInst *MI, unsigned OpNo,
46+
const MCSubtargetInfo &STI, raw_ostream &O);
4547
void printNamedBit(const MCInst *MI, unsigned OpNo, raw_ostream &O,
4648
StringRef BitName);
4749
void printOffset(const MCInst *MI, unsigned OpNo, const MCSubtargetInfo &STI,

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

Lines changed: 17 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -87,9 +87,10 @@ class AMDGPUMCCodeEmitter : public MCCodeEmitter {
8787
const MCSubtargetInfo &STI) const;
8888

8989
/// Encode an fp or int literal.
90-
std::optional<uint32_t> getLitEncoding(const MCOperand &MO,
91-
const MCOperandInfo &OpInfo,
92-
const MCSubtargetInfo &STI) const;
90+
std::optional<uint64_t>
91+
getLitEncoding(const MCOperand &MO, const MCOperandInfo &OpInfo,
92+
const MCSubtargetInfo &STI,
93+
bool HasMandatoryLiteral = false) const;
9394

9495
void getBinaryCodeForInstr(const MCInst &MI, SmallVectorImpl<MCFixup> &Fixups,
9596
APInt &Inst, APInt &Scratch,
@@ -265,10 +266,9 @@ static uint32_t getLit64Encoding(uint64_t Val, const MCSubtargetInfo &STI,
265266
: 255;
266267
}
267268

268-
std::optional<uint32_t>
269-
AMDGPUMCCodeEmitter::getLitEncoding(const MCOperand &MO,
270-
const MCOperandInfo &OpInfo,
271-
const MCSubtargetInfo &STI) const {
269+
std::optional<uint64_t> AMDGPUMCCodeEmitter::getLitEncoding(
270+
const MCOperand &MO, const MCOperandInfo &OpInfo,
271+
const MCSubtargetInfo &STI, bool HasMandatoryLiteral) const {
272272
int64_t Imm;
273273
if (MO.isExpr()) {
274274
if (!MO.getExpr()->evaluateAsAbsolute(Imm))
@@ -303,9 +303,13 @@ AMDGPUMCCodeEmitter::getLitEncoding(const MCOperand &MO,
303303

304304
case AMDGPU::OPERAND_REG_INLINE_C_FP64:
305305
case AMDGPU::OPERAND_REG_INLINE_AC_FP64:
306-
case AMDGPU::OPERAND_REG_IMM_FP64:
307306
return getLit64Encoding(static_cast<uint64_t>(Imm), STI, true);
308307

308+
case AMDGPU::OPERAND_REG_IMM_FP64: {
309+
auto Enc = getLit64Encoding(static_cast<uint64_t>(Imm), STI, true);
310+
return (HasMandatoryLiteral && Enc == 255) ? 254 : Enc;
311+
}
312+
309313
case AMDGPU::OPERAND_REG_IMM_INT16:
310314
case AMDGPU::OPERAND_REG_INLINE_C_INT16:
311315
return getLit16IntEncoding(static_cast<uint32_t>(Imm), STI);
@@ -339,6 +343,7 @@ AMDGPUMCCodeEmitter::getLitEncoding(const MCOperand &MO,
339343

340344
case AMDGPU::OPERAND_KIMM32:
341345
case AMDGPU::OPERAND_KIMM16:
346+
case AMDGPU::OPERAND_KIMM64:
342347
return MO.getImm();
343348
default:
344349
llvm_unreachable("invalid operand size");
@@ -685,7 +690,10 @@ void AMDGPUMCCodeEmitter::getMachineOpValueCommon(
685690

686691
const MCInstrDesc &Desc = MCII.get(MI.getOpcode());
687692
if (AMDGPU::isSISrcOperand(Desc, OpNo)) {
688-
if (auto Enc = getLitEncoding(MO, Desc.operands()[OpNo], STI)) {
693+
bool HasMandatoryLiteral =
694+
AMDGPU::hasNamedOperand(MI.getOpcode(), AMDGPU::OpName::imm);
695+
if (auto Enc = getLitEncoding(MO, Desc.operands()[OpNo], STI,
696+
HasMandatoryLiteral)) {
689697
Op = *Enc;
690698
return;
691699
}

llvm/lib/Target/AMDGPU/SIDefines.h

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -229,6 +229,7 @@ enum OperandType : unsigned {
229229
/// Operand with 32-bit immediate that uses the constant bus.
230230
OPERAND_KIMM32,
231231
OPERAND_KIMM16,
232+
OPERAND_KIMM64,
232233

233234
/// Operands with an AccVGPR register or inline constant
234235
OPERAND_REG_INLINE_AC_INT32,
@@ -254,7 +255,7 @@ enum OperandType : unsigned {
254255
OPERAND_SRC_LAST = OPERAND_REG_INLINE_C_LAST,
255256

256257
OPERAND_KIMM_FIRST = OPERAND_KIMM32,
257-
OPERAND_KIMM_LAST = OPERAND_KIMM16
258+
OPERAND_KIMM_LAST = OPERAND_KIMM64
258259

259260
};
260261
}

llvm/lib/Target/AMDGPU/SIInstrInfo.cpp

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4442,6 +4442,7 @@ bool SIInstrInfo::isInlineConstant(int64_t Imm, uint8_t OperandType) const {
44424442
}
44434443
case AMDGPU::OPERAND_KIMM32:
44444444
case AMDGPU::OPERAND_KIMM16:
4445+
case AMDGPU::OPERAND_KIMM64:
44454446
return false;
44464447
case AMDGPU::OPERAND_INPUT_MODS:
44474448
case MCOI::OPERAND_IMMEDIATE:
@@ -4867,6 +4868,7 @@ bool SIInstrInfo::verifyInstruction(const MachineInstr &MI,
48674868
break;
48684869
case MCOI::OPERAND_IMMEDIATE:
48694870
case AMDGPU::OPERAND_KIMM32:
4871+
case AMDGPU::OPERAND_KIMM64:
48704872
// Check if this operand is an immediate.
48714873
// FrameIndex operands will be replaced by immediates, so they are
48724874
// allowed.

0 commit comments

Comments
 (0)