Skip to content

Commit aded4f0

Browse files
committed
[X86-64] Support Intel AMX instructions
Summary: INTEL ADVANCED MATRIX EXTENSIONS (AMX). AMX is a new programming paradigm, it has a set of 2-dimensional registers (TILES) representing sub-arrays from a larger 2-dimensional memory image and operate on TILES. Spec can be found in Chapter 3 here https://software.intel.com/content/www/us/en/develop/download/intel-architecture-instruction-set-extensions-programming-reference.html Reviewers: LuoYuanke, annita.zhang, pengfei, RKSimon, xiangzhangllvm Reviewed By: xiangzhangllvm Subscribers: hiraditya, llvm-commits Tags: #llvm Differential Revision: https://reviews.llvm.org/D82705
1 parent 99c4207 commit aded4f0

34 files changed

+1564
-16
lines changed

llvm/include/llvm/Support/X86DisassemblerDecoderCommon.h

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -323,6 +323,7 @@ typedef uint16_t InstrUID;
323323
ENUM_ENTRY(MODRM_SPLITRM) \
324324
ENUM_ENTRY(MODRM_SPLITMISC) \
325325
ENUM_ENTRY(MODRM_SPLITREG) \
326+
ENUM_ENTRY(MODRM_SPLITREGM) \
326327
ENUM_ENTRY(MODRM_FULL)
327328

328329
#define ENUM_ENTRY(n) n,
@@ -361,6 +362,7 @@ enum ModRMDecisionType {
361362
ENUM_ENTRY(ENCODING_RM_CD16,"R/M operand with CDisp scaling of 16") \
362363
ENUM_ENTRY(ENCODING_RM_CD32,"R/M operand with CDisp scaling of 32") \
363364
ENUM_ENTRY(ENCODING_RM_CD64,"R/M operand with CDisp scaling of 64") \
365+
ENUM_ENTRY(ENCODING_SIB, "Force SIB operand in ModR/M byte.") \
364366
ENUM_ENTRY(ENCODING_VSIB, "VSIB operand in ModR/M byte.") \
365367
ENUM_ENTRY(ENCODING_VSIB_CD2, "VSIB operand with CDisp scaling of 2") \
366368
ENUM_ENTRY(ENCODING_VSIB_CD4, "VSIB operand with CDisp scaling of 4") \
@@ -411,6 +413,7 @@ enum OperandEncoding {
411413
ENUM_ENTRY(TYPE_IMM, "immediate operand") \
412414
ENUM_ENTRY(TYPE_UIMM8, "1-byte unsigned immediate operand") \
413415
ENUM_ENTRY(TYPE_M, "Memory operand") \
416+
ENUM_ENTRY(TYPE_MSIB, "Memory operand force sib encoding") \
414417
ENUM_ENTRY(TYPE_MVSIBX, "Memory operand using XMM index") \
415418
ENUM_ENTRY(TYPE_MVSIBY, "Memory operand using YMM index") \
416419
ENUM_ENTRY(TYPE_MVSIBZ, "Memory operand using ZMM index") \
@@ -424,6 +427,7 @@ enum OperandEncoding {
424427
ENUM_ENTRY(TYPE_ZMM, "64-byte") \
425428
ENUM_ENTRY(TYPE_VK, "mask register") \
426429
ENUM_ENTRY(TYPE_VK_PAIR, "mask register pair") \
430+
ENUM_ENTRY(TYPE_TMM, "tile") \
427431
ENUM_ENTRY(TYPE_SEGMENTREG, "Segment register operand") \
428432
ENUM_ENTRY(TYPE_DEBUGREG, "Debug register operand") \
429433
ENUM_ENTRY(TYPE_CONTROLREG, "Control register operand") \

llvm/lib/Support/Host.cpp

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1392,8 +1392,8 @@ bool sys::getHostCPUFeatures(StringMap<bool> &Features) {
13921392
// If CPUID indicates support for XSAVE, XRESTORE and AVX, and XGETBV
13931393
// indicates that the AVX registers will be saved and restored on context
13941394
// switch, then we have full AVX support.
1395-
bool HasAVXSave = ((ECX >> 27) & 1) && ((ECX >> 28) & 1) &&
1396-
!getX86XCR0(&EAX, &EDX) && ((EAX & 0x6) == 0x6);
1395+
bool HasXSave = ((ECX >> 27) & 1) && !getX86XCR0(&EAX, &EDX);
1396+
bool HasAVXSave = HasXSave && ((ECX >> 28) & 1) && ((EAX & 0x6) == 0x6);
13971397
#if defined(__APPLE__)
13981398
// Darwin lazily saves the AVX512 context on first use: trust that the OS will
13991399
// save the AVX512 context if we use AVX512 instructions, even the bit is not
@@ -1403,6 +1403,9 @@ bool sys::getHostCPUFeatures(StringMap<bool> &Features) {
14031403
// AVX512 requires additional context to be saved by the OS.
14041404
bool HasAVX512Save = HasAVXSave && ((EAX & 0xe0) == 0xe0);
14051405
#endif
1406+
// AMX requires additional context to be saved by the OS.
1407+
const unsigned AMXBits = (1 << 17) | (1 << 18);
1408+
bool HasAMXSave = HasXSave && ((EAX & AMXBits) == AMXBits);
14061409

14071410
Features["avx"] = HasAVXSave;
14081411
Features["fma"] = ((ECX >> 12) & 1) && HasAVXSave;
@@ -1493,6 +1496,9 @@ bool sys::getHostCPUFeatures(StringMap<bool> &Features) {
14931496
// detecting features using the "-march=native" flag.
14941497
// For more info, see X86 ISA docs.
14951498
Features["pconfig"] = HasLeaf7 && ((EDX >> 18) & 1);
1499+
Features["amx-bf16"] = HasLeaf7 && ((EDX >> 22) & 1) && HasAMXSave;
1500+
Features["amx-tile"] = HasLeaf7 && ((EDX >> 24) & 1) && HasAMXSave;
1501+
Features["amx-int8"] = HasLeaf7 && ((EDX >> 25) & 1) && HasAMXSave;
14961502
bool HasLeaf7Subleaf1 =
14971503
MaxLevel >= 7 && !getX86CpuIDAndInfoEx(0x7, 0x1, &EAX, &EBX, &ECX, &EDX);
14981504
Features["avx512bf16"] = HasLeaf7Subleaf1 && ((EAX >> 5) & 1) && HasAVX512Save;

llvm/lib/Target/X86/AsmParser/X86Operand.h

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -315,6 +315,11 @@ struct X86Operand final : public MCParsedAsmOperand {
315315
bool isMem512() const {
316316
return Kind == Memory && (!Mem.Size || Mem.Size == 512);
317317
}
318+
319+
bool isSibMem() const {
320+
return isMem() && Mem.BaseReg != X86::RIP && Mem.BaseReg != X86::EIP;
321+
}
322+
318323
bool isMemIndexReg(unsigned LowR, unsigned HighR) const {
319324
assert(Kind == Memory && "Invalid access!");
320325
return Mem.IndexReg >= LowR && Mem.IndexReg <= HighR;

llvm/lib/Target/X86/Disassembler/X86Disassembler.cpp

Lines changed: 30 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -166,6 +166,9 @@ static InstrUID decode(OpcodeType type, InstructionContext insnContext,
166166
if (modFromModRM(modRM) == 0x3)
167167
return modRMTable[dec->instructionIDs + ((modRM & 0x38) >> 3) + 8];
168168
return modRMTable[dec->instructionIDs + ((modRM & 0x38) >> 3)];
169+
case MODRM_SPLITREGM:
170+
assert(modFromModRM(modRM) == 0x3);
171+
return modRMTable[dec->instructionIDs+(modRM & 0x7)];
169172
case MODRM_SPLITMISC:
170173
if (modFromModRM(modRM) == 0x3)
171174
return modRMTable[dec->instructionIDs + (modRM & 0x3f) + 8];
@@ -776,6 +779,10 @@ static int readModRM(struct InternalInstruction *insn) {
776779
return prefix##_YMM0 + index; \
777780
case TYPE_XMM: \
778781
return prefix##_XMM0 + index; \
782+
case TYPE_TMM: \
783+
if (index > 7) \
784+
*valid = 0; \
785+
return prefix##_TMM0 + index; \
779786
case TYPE_VK: \
780787
index &= 0xf; \
781788
if (index > 7) \
@@ -849,6 +856,7 @@ static int fixupReg(struct InternalInstruction *insn,
849856
if (!valid)
850857
return -1;
851858
break;
859+
case ENCODING_SIB:
852860
CASE_ENCODING_RM:
853861
if (insn->eaBase >= insn->eaRegBase) {
854862
insn->eaBase = (EABase)fixupRMValue(
@@ -1533,6 +1541,15 @@ static int readOperands(struct InternalInstruction *insn) {
15331541
if (Op.encoding != ENCODING_REG && insn->eaDisplacement == EA_DISP_8)
15341542
insn->displacement *= 1 << (Op.encoding - ENCODING_VSIB);
15351543
break;
1544+
case ENCODING_SIB:
1545+
// Reject if SIB wasn't used.
1546+
if (insn->eaBase != EA_BASE_sib && insn->eaBase != EA_BASE_sib64)
1547+
return -1;
1548+
if (readModRM(insn))
1549+
return -1;
1550+
if (fixupReg(insn, &Op))
1551+
return -1;
1552+
break;
15361553
case ENCODING_REG:
15371554
CASE_ENCODING_RM:
15381555
if (readModRM(insn))
@@ -2006,9 +2023,11 @@ static bool translateRMRegister(MCInst &mcInst,
20062023
/// @param mcInst - The MCInst to append to.
20072024
/// @param insn - The instruction to extract Mod, R/M, and SIB fields
20082025
/// from.
2026+
/// @param ForceSIB - The instruction must use SIB.
20092027
/// @return - 0 on success; nonzero otherwise
20102028
static bool translateRMMemory(MCInst &mcInst, InternalInstruction &insn,
2011-
const MCDisassembler *Dis) {
2029+
const MCDisassembler *Dis,
2030+
bool ForceSIB = false) {
20122031
// Addresses in an MCInst are represented as five operands:
20132032
// 1. basereg (register) The R/M base, or (if there is a SIB) the
20142033
// SIB base
@@ -2067,11 +2086,12 @@ static bool translateRMMemory(MCInst &mcInst, InternalInstruction &insn,
20672086
// -Any base register used other than ESP/RSP/R12D/R12. Using these as a
20682087
// base always requires a SIB byte.
20692088
// -A scale other than 1 is used.
2070-
if (insn.sibScale != 1 ||
2071-
(insn.sibBase == SIB_BASE_NONE && insn.mode != MODE_64BIT) ||
2072-
(insn.sibBase != SIB_BASE_NONE &&
2073-
insn.sibBase != SIB_BASE_ESP && insn.sibBase != SIB_BASE_RSP &&
2074-
insn.sibBase != SIB_BASE_R12D && insn.sibBase != SIB_BASE_R12)) {
2089+
if (!ForceSIB &&
2090+
(insn.sibScale != 1 ||
2091+
(insn.sibBase == SIB_BASE_NONE && insn.mode != MODE_64BIT) ||
2092+
(insn.sibBase != SIB_BASE_NONE &&
2093+
insn.sibBase != SIB_BASE_ESP && insn.sibBase != SIB_BASE_RSP &&
2094+
insn.sibBase != SIB_BASE_R12D && insn.sibBase != SIB_BASE_R12))) {
20752095
indexReg = MCOperand::createReg(insn.addressSize == 4 ? X86::EIZ :
20762096
X86::RIZ);
20772097
} else
@@ -2182,6 +2202,7 @@ static bool translateRM(MCInst &mcInst, const OperandSpecifier &operand,
21822202
case TYPE_XMM:
21832203
case TYPE_YMM:
21842204
case TYPE_ZMM:
2205+
case TYPE_TMM:
21852206
case TYPE_VK_PAIR:
21862207
case TYPE_VK:
21872208
case TYPE_DEBUGREG:
@@ -2193,6 +2214,8 @@ static bool translateRM(MCInst &mcInst, const OperandSpecifier &operand,
21932214
case TYPE_MVSIBY:
21942215
case TYPE_MVSIBZ:
21952216
return translateRMMemory(mcInst, insn, Dis);
2217+
case TYPE_MSIB:
2218+
return translateRMMemory(mcInst, insn, Dis, true);
21962219
}
21972220
}
21982221

@@ -2242,6 +2265,7 @@ static bool translateOperand(MCInst &mcInst, const OperandSpecifier &operand,
22422265
return false;
22432266
case ENCODING_WRITEMASK:
22442267
return translateMaskRegister(mcInst, insn.writemask);
2268+
case ENCODING_SIB:
22452269
CASE_ENCODING_RM:
22462270
CASE_ENCODING_VSIB:
22472271
return translateRM(mcInst, operand, insn, Dis);

llvm/lib/Target/X86/Disassembler/X86DisassemblerDecoder.h

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -380,6 +380,17 @@ namespace X86Disassembler {
380380
ENTRY(BND2) \
381381
ENTRY(BND3)
382382

383+
#undef REGS_TMM
384+
#define REGS_TMM \
385+
ENTRY(TMM0) \
386+
ENTRY(TMM1) \
387+
ENTRY(TMM2) \
388+
ENTRY(TMM3) \
389+
ENTRY(TMM4) \
390+
ENTRY(TMM5) \
391+
ENTRY(TMM6) \
392+
ENTRY(TMM7)
393+
383394
#define ALL_EA_BASES \
384395
EA_BASES_16BIT \
385396
EA_BASES_32BIT \
@@ -404,6 +415,7 @@ namespace X86Disassembler {
404415
REGS_DEBUG \
405416
REGS_CONTROL \
406417
REGS_BOUND \
418+
REGS_TMM \
407419
ENTRY(RIP)
408420

409421
/// All possible values of the base field for effective-address

llvm/lib/Target/X86/MCTargetDesc/X86BaseInfo.h

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -623,6 +623,15 @@ namespace X86II {
623623
/// information. In the intel manual these are represented as /0, /1, ...
624624
///
625625

626+
// Instructions operate on a register Reg/Opcode operand not the r/m field.
627+
MRMr0 = 21,
628+
629+
/// MRMSrcMem - But force to use the SIB field.
630+
MRMSrcMemFSIB = 22,
631+
632+
/// MRMDestMem - But force to use the SIB field.
633+
MRMDestMemFSIB = 23,
634+
626635
/// MRMDestMem - This form is used for instructions that use the Mod/RM byte
627636
/// to specify a destination, which in this case is memory.
628637
///
@@ -1082,8 +1091,10 @@ namespace X86II {
10821091
case X86II::PrefixByte:
10831092
return -1;
10841093
case X86II::MRMDestMem:
1094+
case X86II::MRMDestMemFSIB:
10851095
return 0;
10861096
case X86II::MRMSrcMem:
1097+
case X86II::MRMSrcMemFSIB:
10871098
// Start from 1, skip any registers encoded in VEX_VVVV or I8IMM, or a
10881099
// mask register.
10891100
return 1 + HasVEX_4V + HasEVEX_K;
@@ -1103,6 +1114,7 @@ namespace X86II {
11031114
case X86II::MRMSrcRegOp4:
11041115
case X86II::MRMSrcRegCC:
11051116
case X86II::MRMXrCC:
1117+
case X86II::MRMr0:
11061118
case X86II::MRMXr:
11071119
case X86II::MRM0r: case X86II::MRM1r:
11081120
case X86II::MRM2r: case X86II::MRM3r:

llvm/lib/Target/X86/MCTargetDesc/X86MCCodeEmitter.cpp

Lines changed: 34 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -78,7 +78,8 @@ class X86MCCodeEmitter : public MCCodeEmitter {
7878
void emitMemModRMByte(const MCInst &MI, unsigned Op, unsigned RegOpcodeField,
7979
uint64_t TSFlags, bool HasREX, uint64_t StartByte,
8080
raw_ostream &OS, SmallVectorImpl<MCFixup> &Fixups,
81-
const MCSubtargetInfo &STI) const;
81+
const MCSubtargetInfo &STI,
82+
bool ForceSIB = false) const;
8283

8384
bool emitPrefixImpl(unsigned &CurOp, const MCInst &MI,
8485
const MCSubtargetInfo &STI, raw_ostream &OS) const;
@@ -382,7 +383,8 @@ void X86MCCodeEmitter::emitMemModRMByte(const MCInst &MI, unsigned Op,
382383
uint64_t TSFlags, bool HasREX,
383384
uint64_t StartByte, raw_ostream &OS,
384385
SmallVectorImpl<MCFixup> &Fixups,
385-
const MCSubtargetInfo &STI) const {
386+
const MCSubtargetInfo &STI,
387+
bool ForceSIB) const {
386388
const MCOperand &Disp = MI.getOperand(Op + X86::AddrDisp);
387389
const MCOperand &Base = MI.getOperand(Op + X86::AddrBaseReg);
388390
const MCOperand &Scale = MI.getOperand(Op + X86::AddrScaleAmt);
@@ -395,7 +397,8 @@ void X86MCCodeEmitter::emitMemModRMByte(const MCInst &MI, unsigned Op,
395397
BaseReg == X86::EIP) { // [disp32+rIP] in X86-64 mode
396398
assert(STI.hasFeature(X86::Mode64Bit) &&
397399
"Rip-relative addressing requires 64-bit mode");
398-
assert(IndexReg.getReg() == 0 && "Invalid rip-relative address");
400+
assert(IndexReg.getReg() == 0 && !ForceSIB &&
401+
"Invalid rip-relative address");
399402
emitByte(modRMByte(0, RegOpcodeField, 5), OS);
400403

401404
unsigned Opcode = MI.getOpcode();
@@ -510,7 +513,7 @@ void X86MCCodeEmitter::emitMemModRMByte(const MCInst &MI, unsigned Op,
510513
// 2-7) and absolute references.
511514

512515
if ( // The SIB byte must be used if there is an index register.
513-
IndexReg.getReg() == 0 &&
516+
!ForceSIB && IndexReg.getReg() == 0 &&
514517
// The SIB byte must be used if the base is ESP/RSP/R12, all of which
515518
// encode to an R/M value of 4, which indicates that a SIB byte is
516519
// present.
@@ -883,9 +886,11 @@ void X86MCCodeEmitter::emitVEXOpcodePrefix(int MemOperand, const MCInst &MI,
883886
switch (TSFlags & X86II::FormMask) {
884887
default:
885888
llvm_unreachable("Unexpected form in emitVEXOpcodePrefix!");
889+
case X86II::MRM_C0:
886890
case X86II::RawFrm:
887891
case X86II::PrefixByte:
888892
break;
893+
case X86II::MRMDestMemFSIB:
889894
case X86II::MRMDestMem: {
890895
// MRMDestMem instructions forms:
891896
// MemAddr, src1(ModR/M)
@@ -916,6 +921,7 @@ void X86MCCodeEmitter::emitVEXOpcodePrefix(int MemOperand, const MCInst &MI,
916921
EVEX_R2 = ~(RegEnc >> 4) & 1;
917922
break;
918923
}
924+
case X86II::MRMSrcMemFSIB:
919925
case X86II::MRMSrcMem: {
920926
// MRMSrcMem instructions forms:
921927
// src1(ModR/M), MemAddr
@@ -1097,6 +1103,15 @@ void X86MCCodeEmitter::emitVEXOpcodePrefix(int MemOperand, const MCInst &MI,
10971103
EncodeRC = true;
10981104
break;
10991105
}
1106+
case X86II::MRMr0: {
1107+
// MRMr0 instructions forms:
1108+
// 11:rrr:000
1109+
// dst(ModR/M)
1110+
unsigned RegEnc = getX86RegEncoding(MI, CurOp++);
1111+
VEX_R = ~(RegEnc >> 3) & 1;
1112+
EVEX_R2 = ~(RegEnc >> 4) & 1;
1113+
break;
1114+
}
11001115
case X86II::MRM0r:
11011116
case X86II::MRM1r:
11021117
case X86II::MRM2r:
@@ -1267,6 +1282,11 @@ bool X86MCCodeEmitter::emitREXPrefix(int MemOperand, const MCInst &MI,
12671282
case X86II::MRM7r:
12681283
REX |= isREXExtendedReg(MI, CurOp++) << 0; // REX.B
12691284
break;
1285+
case X86II::MRMr0:
1286+
REX |= isREXExtendedReg(MI, CurOp++) << 2; // REX.R
1287+
break;
1288+
case X86II::MRMDestMemFSIB:
1289+
llvm_unreachable("FSIB format never need REX prefix!");
12701290
}
12711291
if (REX && UsesHighByteReg)
12721292
report_fatal_error(
@@ -1481,6 +1501,7 @@ void X86MCCodeEmitter::encodeInstruction(const MCInst &MI, raw_ostream &OS,
14811501
CurOp = SrcRegNum + 1;
14821502
break;
14831503
}
1504+
case X86II::MRMDestMemFSIB:
14841505
case X86II::MRMDestMem: {
14851506
emitByte(BaseOpcode, OS);
14861507
unsigned SrcRegNum = CurOp + X86::AddrNumOperands;
@@ -1491,8 +1512,9 @@ void X86MCCodeEmitter::encodeInstruction(const MCInst &MI, raw_ostream &OS,
14911512
if (HasVEX_4V) // Skip 1st src (which is encoded in VEX_VVVV)
14921513
++SrcRegNum;
14931514

1515+
bool ForceSIB = (Form == X86II::MRMDestMemFSIB);
14941516
emitMemModRMByte(MI, CurOp, getX86RegNum(MI.getOperand(SrcRegNum)), TSFlags,
1495-
HasREX, StartByte, OS, Fixups, STI);
1517+
HasREX, StartByte, OS, Fixups, STI, ForceSIB);
14961518
CurOp = SrcRegNum + 1;
14971519
break;
14981520
}
@@ -1553,6 +1575,7 @@ void X86MCCodeEmitter::encodeInstruction(const MCInst &MI, raw_ostream &OS,
15531575
getX86RegNum(MI.getOperand(FirstOp)), OS);
15541576
break;
15551577
}
1578+
case X86II::MRMSrcMemFSIB:
15561579
case X86II::MRMSrcMem: {
15571580
unsigned FirstMemOp = CurOp + 1;
15581581

@@ -1564,8 +1587,9 @@ void X86MCCodeEmitter::encodeInstruction(const MCInst &MI, raw_ostream &OS,
15641587

15651588
emitByte(BaseOpcode, OS);
15661589

1590+
bool ForceSIB = (Form == X86II::MRMSrcMemFSIB);
15671591
emitMemModRMByte(MI, FirstMemOp, getX86RegNum(MI.getOperand(CurOp)),
1568-
TSFlags, HasREX, StartByte, OS, Fixups, STI);
1592+
TSFlags, HasREX, StartByte, OS, Fixups, STI, ForceSIB);
15691593
CurOp = FirstMemOp + X86::AddrNumOperands;
15701594
if (HasVEX_I8Reg)
15711595
I8RegNum = getX86RegEncoding(MI, CurOp++);
@@ -1637,6 +1661,10 @@ void X86MCCodeEmitter::encodeInstruction(const MCInst &MI, raw_ostream &OS,
16371661
emitRegModRMByte(MI.getOperand(CurOp++),
16381662
(Form == X86II::MRMXr) ? 0 : Form - X86II::MRM0r, OS);
16391663
break;
1664+
case X86II::MRMr0:
1665+
emitByte(BaseOpcode, OS);
1666+
emitByte(modRMByte(3, getX86RegNum(MI.getOperand(CurOp++)),0), OS);
1667+
break;
16401668

16411669
case X86II::MRMXmCC: {
16421670
unsigned FirstMemOp = CurOp;

llvm/lib/Target/X86/X86.td

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -249,6 +249,14 @@ def FeaturePTWRITE : SubtargetFeature<"ptwrite", "HasPTWRITE", "true",
249249
// target-feature attribute.
250250
def FeatureDeprecatedMPX : SubtargetFeature<"mpx", "DeprecatedHasMPX", "false",
251251
"Deprecated. Support MPX instructions">;
252+
def FeatureAMXTILE : SubtargetFeature<"amx-tile", "HasAMXTILE", "true",
253+
"Support AMX-TILE instructions">;
254+
def FeatureAMXINT8 : SubtargetFeature<"amx-int8", "HasAMXINT8", "true",
255+
"Support AMX-INT8 instructions",
256+
[FeatureAMXTILE]>;
257+
def FeatureAMXBF16 : SubtargetFeature<"amx-bf16", "HasAMXBF16", "true",
258+
"Support AMX-BF16 instructions",
259+
[FeatureAMXTILE]>;
252260
def FeatureLEAForSP : SubtargetFeature<"lea-sp", "UseLeaForSP", "true",
253261
"Use LEA for adjusting the stack pointer">;
254262
def FeatureSlowDivide32 : SubtargetFeature<"idivl-to-divb",

0 commit comments

Comments
 (0)