[llvm] 2e27c4e - [AArch64][SME] Add zero instruction
Cullen Rhodes via llvm-commits
llvm-commits at lists.llvm.org
Tue Jul 27 01:36:28 PDT 2021
Author: Cullen Rhodes
Date: 2021-07-27T08:35:45Z
New Revision: 2e27c4e1f187446c84220f75e492f16807d21b12
URL: https://github.com/llvm/llvm-project/commit/2e27c4e1f187446c84220f75e492f16807d21b12
DIFF: https://github.com/llvm/llvm-project/commit/2e27c4e1f187446c84220f75e492f16807d21b12.diff
LOG: [AArch64][SME] Add zero instruction
This patch adds the zero instruction for zeroing a list of 64-bit
element ZA tiles. The instruction takes a list of up to eight tiles
ZA0.D-ZA7.D, which must be in order, e.g.
zero {za0.d,za1.d,za2.d,za3.d,za4.d,za5.d,za6.d,za7.d}
zero {za1.d,za3.d,za5.d,za7.d}
The assembler also accepts 32-bit, 16-bit and 8-bit element tiles which
are mapped to corresponding 64-bit element tiles in accordance with the
architecturally defined mapping between different element size tiles,
e.g.
* Zeroing ZA0.B, or the entire array name ZA, is equivalent to zeroing
all eight 64-bit element tiles ZA0.D to ZA7.D.
* Zeroing ZA0.S is equivalent to zeroing ZA0.D and ZA4.D.
The preferred disassembly of this instruction uses the shortest list of
tile names that represent the encoded immediate mask, e.g.
* An immediate which encodes 64-bit element tiles ZA0.D, ZA1.D, ZA4.D and
ZA5.D is disassembled as {ZA0.S, ZA1.S}.
* An immediate which encodes 64-bit element tiles ZA0.D, ZA2.D, ZA4.D and
ZA6.D is disassembled as {ZA0.H}.
* An all-ones immediate is disassembled as {ZA}.
* An all-zeros immediate is disassembled as an empty list {}.
This patch adds the MatrixTileList asm operand and related parsing to support
this.
Depends on D105570.
The reference can be found here:
https://developer.arm.com/documentation/ddi0602/2021-06
Reviewed By: david-arm
Differential Revision: https://reviews.llvm.org/D105575
Added:
llvm/test/MC/AArch64/SME/zero-diagnostics.s
llvm/test/MC/AArch64/SME/zero.s
Modified:
llvm/lib/Target/AArch64/AArch64RegisterInfo.td
llvm/lib/Target/AArch64/AArch64SMEInstrInfo.td
llvm/lib/Target/AArch64/AsmParser/AArch64AsmParser.cpp
llvm/lib/Target/AArch64/Disassembler/AArch64Disassembler.cpp
llvm/lib/Target/AArch64/MCTargetDesc/AArch64InstPrinter.cpp
llvm/lib/Target/AArch64/MCTargetDesc/AArch64InstPrinter.h
llvm/lib/Target/AArch64/MCTargetDesc/AArch64MCCodeEmitter.cpp
llvm/lib/Target/AArch64/SMEInstrFormats.td
Removed:
################################################################################
diff --git a/llvm/lib/Target/AArch64/AArch64RegisterInfo.td b/llvm/lib/Target/AArch64/AArch64RegisterInfo.td
index 9d689a588d39a..07dee3ce1fbc4 100644
--- a/llvm/lib/Target/AArch64/AArch64RegisterInfo.td
+++ b/llvm/lib/Target/AArch64/AArch64RegisterInfo.td
@@ -1352,6 +1352,22 @@ class MatrixOperand<RegisterClass RC, int EltSize> : RegisterOperand<RC> {
def MatrixOp : MatrixOperand<MPR, 0>;
+class MatrixTileListAsmOperand : AsmOperandClass {
+ let Name = "MatrixTileList";
+ let ParserMethod = "tryParseMatrixTileList";
+ let RenderMethod = "addMatrixTileListOperands";
+ let PredicateMethod = "isMatrixTileList";
+}
+
+class MatrixTileListOperand : Operand<i8> {
+ let ParserMatchClass = MatrixTileListAsmOperand<>;
+ let DecoderMethod = "DecodeMatrixTileListRegisterClass";
+ let EncoderMethod = "EncodeMatrixTileListRegisterClass";
+ let PrintMethod = "printMatrixTileList";
+}
+
+def MatrixTileList : MatrixTileListOperand<>;
+
def MatrixIndexGPR32_12_15 : RegisterClass<"AArch64", [i32], 32, (sequence "W%u", 12, 15)> {
let DiagnosticType = "InvalidMatrixIndexGPR32_12_15";
}
diff --git a/llvm/lib/Target/AArch64/AArch64SMEInstrInfo.td b/llvm/lib/Target/AArch64/AArch64SMEInstrInfo.td
index 2ef3e9e805334..6a0fa2fc4f4e0 100644
--- a/llvm/lib/Target/AArch64/AArch64SMEInstrInfo.td
+++ b/llvm/lib/Target/AArch64/AArch64SMEInstrInfo.td
@@ -88,6 +88,12 @@ defm STR_ZA : sme_spill<"str">;
defm INSERT_MXIPZ : sme_vector_to_tile<"mova">;
defm EXTRACT_ZPMXI : sme_tile_to_vector<"mova">;
+//===----------------------------------------------------------------------===//
+// Zero instruction
+//===----------------------------------------------------------------------===//
+
+defm ZERO_M : sme_zero<"zero">;
+
//===----------------------------------------------------------------------===//
// Mode selection and state access instructions
//===----------------------------------------------------------------------===//
diff --git a/llvm/lib/Target/AArch64/AsmParser/AArch64AsmParser.cpp b/llvm/lib/Target/AArch64/AsmParser/AArch64AsmParser.cpp
index edbab0a00301f..f27e9b2ef0f04 100644
--- a/llvm/lib/Target/AArch64/AsmParser/AArch64AsmParser.cpp
+++ b/llvm/lib/Target/AArch64/AsmParser/AArch64AsmParser.cpp
@@ -18,6 +18,7 @@
#include "llvm/ADT/APInt.h"
#include "llvm/ADT/ArrayRef.h"
#include "llvm/ADT/STLExtras.h"
+#include "llvm/ADT/SmallSet.h"
#include "llvm/ADT/SmallVector.h"
#include "llvm/ADT/StringExtras.h"
#include "llvm/ADT/StringMap.h"
@@ -262,6 +263,7 @@ class AArch64AsmParser : public MCTargetAsmParser {
template <RegKind VectorKind>
OperandMatchResultTy tryParseVectorList(OperandVector &Operands,
bool ExpectMatch = false);
+ OperandMatchResultTy tryParseMatrixTileList(OperandVector &Operands);
OperandMatchResultTy tryParseSVEPattern(OperandVector &Operands);
OperandMatchResultTy tryParseGPR64x8(OperandVector &Operands);
@@ -322,6 +324,7 @@ class AArch64Operand : public MCParsedAsmOperand {
k_CondCode,
k_Register,
k_MatrixRegister,
+ k_MatrixTileList,
k_SVCR,
k_VectorList,
k_VectorIndex,
@@ -383,6 +386,10 @@ class AArch64Operand : public MCParsedAsmOperand {
MatrixKind Kind;
};
+ struct MatrixTileListOp {
+ unsigned RegMask = 0;
+ };
+
struct VectorListOp {
unsigned RegNum;
unsigned Count;
@@ -460,6 +467,7 @@ class AArch64Operand : public MCParsedAsmOperand {
struct TokOp Tok;
struct RegOp Reg;
struct MatrixRegOp MatrixReg;
+ struct MatrixTileListOp MatrixTileList;
struct VectorListOp VectorList;
struct VectorIndexOp VectorIndex;
struct ImmOp Imm;
@@ -512,6 +520,9 @@ class AArch64Operand : public MCParsedAsmOperand {
case k_MatrixRegister:
MatrixReg = o.MatrixReg;
break;
+ case k_MatrixTileList:
+ MatrixTileList = o.MatrixTileList;
+ break;
case k_VectorList:
VectorList = o.VectorList;
break;
@@ -622,6 +633,11 @@ class AArch64Operand : public MCParsedAsmOperand {
return MatrixReg.Kind;
}
+ unsigned getMatrixTileListRegMask() const {
+ assert(isMatrixTileList() && "Invalid access!");
+ return MatrixTileList.RegMask;
+ }
+
RegConstraintEqualityTy getRegEqualityTy() const {
assert(Kind == k_Register && "Invalid access!");
return Reg.EqualityTy;
@@ -1143,6 +1159,7 @@ class AArch64Operand : public MCParsedAsmOperand {
}
bool isMatrix() const { return Kind == k_MatrixRegister; }
+ bool isMatrixTileList() const { return Kind == k_MatrixTileList; }
template <unsigned Class> bool isSVEVectorReg() const {
RegKind RK;
@@ -1643,6 +1660,13 @@ class AArch64Operand : public MCParsedAsmOperand {
FirstRegs[(unsigned)RegTy][0]));
}
+ void addMatrixTileListOperands(MCInst &Inst, unsigned N) const {
+ assert(N == 1 && "Invalid number of operands!");
+ unsigned RegMask = getMatrixTileListRegMask();
+ assert(RegMask <= 0xFF && "Invalid mask!");
+ Inst.addOperand(MCOperand::createImm(RegMask));
+ }
+
void addVectorIndexOperands(MCInst &Inst, unsigned N) const {
assert(N == 1 && "Invalid number of operands!");
Inst.addOperand(MCOperand::createImm(getVectorIndex()));
@@ -2012,6 +2036,45 @@ class AArch64Operand : public MCParsedAsmOperand {
return Op;
}
+ static std::unique_ptr<AArch64Operand>
+ CreateMatrixTileList(unsigned RegMask, SMLoc S, SMLoc E, MCContext &Ctx) {
+ auto Op = std::make_unique<AArch64Operand>(k_MatrixTileList, Ctx);
+ Op->MatrixTileList.RegMask = RegMask;
+ Op->StartLoc = S;
+ Op->EndLoc = E;
+ return Op;
+ }
+
+ static void ComputeRegsForAlias(unsigned Reg, SmallSet<unsigned, 8> &OutRegs,
+ const unsigned ElementWidth) {
+ static std::map<std::pair<unsigned, unsigned>, std::vector<unsigned>>
+ RegMap = {
+ {{0, AArch64::ZAB0},
+ {AArch64::ZAD0, AArch64::ZAD1, AArch64::ZAD2, AArch64::ZAD3,
+ AArch64::ZAD4, AArch64::ZAD5, AArch64::ZAD6, AArch64::ZAD7}},
+ {{8, AArch64::ZAB0},
+ {AArch64::ZAD0, AArch64::ZAD1, AArch64::ZAD2, AArch64::ZAD3,
+ AArch64::ZAD4, AArch64::ZAD5, AArch64::ZAD6, AArch64::ZAD7}},
+ {{16, AArch64::ZAH0},
+ {AArch64::ZAD0, AArch64::ZAD2, AArch64::ZAD4, AArch64::ZAD6}},
+ {{16, AArch64::ZAH1},
+ {AArch64::ZAD1, AArch64::ZAD3, AArch64::ZAD5, AArch64::ZAD7}},
+ {{32, AArch64::ZAS0}, {AArch64::ZAD0, AArch64::ZAD4}},
+ {{32, AArch64::ZAS1}, {AArch64::ZAD1, AArch64::ZAD5}},
+ {{32, AArch64::ZAS2}, {AArch64::ZAD2, AArch64::ZAD6}},
+ {{32, AArch64::ZAS3}, {AArch64::ZAD3, AArch64::ZAD7}},
+ };
+
+ if (ElementWidth == 64)
+ OutRegs.insert(Reg);
+ else {
+ std::vector<unsigned> Regs = RegMap[std::make_pair(ElementWidth, Reg)];
+ assert(!Regs.empty() && "Invalid tile or element width!");
+ for (auto OutReg : Regs)
+ OutRegs.insert(OutReg);
+ }
+ }
+
static std::unique_ptr<AArch64Operand> CreateImm(const MCExpr *Val, SMLoc S,
SMLoc E, MCContext &Ctx) {
auto Op = std::make_unique<AArch64Operand>(k_Immediate, Ctx);
@@ -2235,6 +2298,15 @@ void AArch64Operand::print(raw_ostream &OS) const {
case k_MatrixRegister:
OS << "<matrix " << getMatrixReg() << ">";
break;
+ case k_MatrixTileList: {
+ OS << "<matrixlist ";
+ unsigned RegMask = getMatrixTileListRegMask();
+ unsigned MaxBits = 8;
+ for (unsigned I = MaxBits; I > 0; --I)
+ OS << ((RegMask & (1 << (I - 1))) >> (I - 1));
+ OS << '>';
+ break;
+ }
case k_SVCR: {
OS << getSVCR();
break;
@@ -2418,6 +2490,26 @@ static unsigned matchSVEPredicateVectorRegName(StringRef Name) {
.Default(0);
}
+static unsigned matchMatrixTileListRegName(StringRef Name) {
+ return StringSwitch<unsigned>(Name.lower())
+ .Case("za0.d", AArch64::ZAD0)
+ .Case("za1.d", AArch64::ZAD1)
+ .Case("za2.d", AArch64::ZAD2)
+ .Case("za3.d", AArch64::ZAD3)
+ .Case("za4.d", AArch64::ZAD4)
+ .Case("za5.d", AArch64::ZAD5)
+ .Case("za6.d", AArch64::ZAD6)
+ .Case("za7.d", AArch64::ZAD7)
+ .Case("za0.s", AArch64::ZAS0)
+ .Case("za1.s", AArch64::ZAS1)
+ .Case("za2.s", AArch64::ZAS2)
+ .Case("za3.s", AArch64::ZAS3)
+ .Case("za0.h", AArch64::ZAH0)
+ .Case("za1.h", AArch64::ZAH1)
+ .Case("za0.b", AArch64::ZAB0)
+ .Default(0);
+}
+
static unsigned matchMatrixRegName(StringRef Name) {
return StringSwitch<unsigned>(Name.lower())
.Case("za", AArch64::ZA)
@@ -3763,6 +3855,120 @@ bool AArch64AsmParser::parseSymbolicImmVal(const MCExpr *&ImmVal) {
return false;
}
+OperandMatchResultTy
+AArch64AsmParser::tryParseMatrixTileList(OperandVector &Operands) {
+ MCAsmParser &Parser = getParser();
+
+ if (Parser.getTok().isNot(AsmToken::LCurly))
+ return MatchOperand_NoMatch;
+
+ auto ParseMatrixTile = [this, &Parser](unsigned &Reg,
+ unsigned &ElementWidth) {
+ StringRef Name = Parser.getTok().getString();
+ size_t DotPosition = Name.find('.');
+ if (DotPosition == StringRef::npos)
+ return MatchOperand_NoMatch;
+
+ unsigned RegNum = matchMatrixTileListRegName(Name);
+ if (!RegNum)
+ return MatchOperand_NoMatch;
+
+ StringRef Tail = Name.drop_front(DotPosition);
+ const Optional<std::pair<int, int>> &KindRes =
+ parseVectorKind(Tail, RegKind::Matrix);
+ if (!KindRes) {
+ TokError("Expected the register to be followed by element width suffix");
+ return MatchOperand_ParseFail;
+ }
+ ElementWidth = KindRes->second;
+ Reg = RegNum;
+ Parser.Lex(); // Eat the register.
+ return MatchOperand_Success;
+ };
+
+ SMLoc S = getLoc();
+ auto LCurly = Parser.getTok();
+ Parser.Lex(); // Eat left bracket token.
+
+ // Empty matrix list
+ if (parseOptionalToken(AsmToken::RCurly)) {
+ Operands.push_back(AArch64Operand::CreateMatrixTileList(
+ /*RegMask=*/0, S, getLoc(), getContext()));
+ return MatchOperand_Success;
+ }
+
+ // Try parse {za} alias early
+ if (Parser.getTok().getString().equals_insensitive("za")) {
+ Parser.Lex(); // Eat 'za'
+
+ if (parseToken(AsmToken::RCurly, "'}' expected"))
+ return MatchOperand_ParseFail;
+
+ Operands.push_back(AArch64Operand::CreateMatrixTileList(
+ /*RegMask=*/0xFF, S, getLoc(), getContext()));
+ return MatchOperand_Success;
+ }
+
+ SMLoc TileLoc = getLoc();
+
+ unsigned FirstReg, ElementWidth;
+ auto ParseRes = ParseMatrixTile(FirstReg, ElementWidth);
+ if (ParseRes != MatchOperand_Success) {
+ Parser.getLexer().UnLex(LCurly);
+ return ParseRes;
+ }
+
+ const MCRegisterInfo *RI = getContext().getRegisterInfo();
+
+ unsigned PrevReg = FirstReg;
+ unsigned Count = 1;
+
+ SmallSet<unsigned, 8> DRegs;
+ AArch64Operand::ComputeRegsForAlias(FirstReg, DRegs, ElementWidth);
+
+ SmallSet<unsigned, 8> SeenRegs;
+ SeenRegs.insert(FirstReg);
+
+ while (parseOptionalToken(AsmToken::Comma)) {
+ TileLoc = getLoc();
+ unsigned Reg, NextElementWidth;
+ ParseRes = ParseMatrixTile(Reg, NextElementWidth);
+ if (ParseRes != MatchOperand_Success)
+ return ParseRes;
+
+ // Element size must match on all regs in the list.
+ if (ElementWidth != NextElementWidth) {
+ Error(TileLoc, "mismatched register size suffix");
+ return MatchOperand_ParseFail;
+ }
+
+ if (RI->getEncodingValue(Reg) <= (RI->getEncodingValue(PrevReg)))
+ Warning(TileLoc, "tile list not in ascending order");
+
+ if (SeenRegs.contains(Reg))
+ Warning(TileLoc, "duplicate tile in list");
+ else {
+ SeenRegs.insert(Reg);
+ AArch64Operand::ComputeRegsForAlias(Reg, DRegs, ElementWidth);
+ }
+
+ PrevReg = Reg;
+ ++Count;
+ }
+
+ if (parseToken(AsmToken::RCurly, "'}' expected"))
+ return MatchOperand_ParseFail;
+
+ unsigned RegMask = 0;
+ for (auto Reg : DRegs)
+ RegMask |= 0x1 << (RI->getEncodingValue(Reg) -
+ RI->getEncodingValue(AArch64::ZAD0));
+ Operands.push_back(
+ AArch64Operand::CreateMatrixTileList(RegMask, S, getLoc(), getContext()));
+
+ return MatchOperand_Success;
+}
+
template <RegKind VectorKind>
OperandMatchResultTy
AArch64AsmParser::tryParseVectorList(OperandVector &Operands,
diff --git a/llvm/lib/Target/AArch64/Disassembler/AArch64Disassembler.cpp b/llvm/lib/Target/AArch64/Disassembler/AArch64Disassembler.cpp
index 2f68dbcb078ff..1ed8a80a46005 100644
--- a/llvm/lib/Target/AArch64/Disassembler/AArch64Disassembler.cpp
+++ b/llvm/lib/Target/AArch64/Disassembler/AArch64Disassembler.cpp
@@ -118,6 +118,10 @@ static DecodeStatus DecodeZPR4RegisterClass(MCInst &Inst, unsigned RegNo,
template <unsigned NumBitsForTile>
static DecodeStatus DecodeMatrixTile(MCInst &Inst, unsigned RegNo,
uint64_t Address, const void *Decoder);
+static DecodeStatus DecodeMatrixTileListRegisterClass(MCInst &Inst,
+ unsigned RegMask,
+ uint64_t Address,
+ const void *Decoder);
static DecodeStatus DecodePPRRegisterClass(MCInst &Inst, unsigned RegNo,
uint64_t Address,
const void *Decoder);
@@ -704,6 +708,16 @@ static DecodeStatus DecodeZPR4RegisterClass(MCInst &Inst, unsigned RegNo,
return Success;
}
+static DecodeStatus DecodeMatrixTileListRegisterClass(MCInst &Inst,
+ unsigned RegMask,
+ uint64_t Address,
+ const void *Decoder) {
+ if (RegMask > 0xFF)
+ return Fail;
+ Inst.addOperand(MCOperand::createImm(RegMask));
+ return Success;
+}
+
static const SmallVector<SmallVector<unsigned, 16>, 5>
MatrixZATileDecoderTable = {
{AArch64::ZAB0},
diff --git a/llvm/lib/Target/AArch64/MCTargetDesc/AArch64InstPrinter.cpp b/llvm/lib/Target/AArch64/MCTargetDesc/AArch64InstPrinter.cpp
index 1e0980515ae3c..cd1bfed9d40d0 100644
--- a/llvm/lib/Target/AArch64/MCTargetDesc/AArch64InstPrinter.cpp
+++ b/llvm/lib/Target/AArch64/MCTargetDesc/AArch64InstPrinter.cpp
@@ -1340,6 +1340,36 @@ void AArch64InstPrinter::printGPRSeqPairsClassOperand(const MCInst *MI,
O << getRegisterName(Even) << ", " << getRegisterName(Odd);
}
+static const unsigned MatrixZADRegisterTable[] = {
+ AArch64::ZAD0, AArch64::ZAD1, AArch64::ZAD2, AArch64::ZAD3,
+ AArch64::ZAD4, AArch64::ZAD5, AArch64::ZAD6, AArch64::ZAD7
+};
+
+void AArch64InstPrinter::printMatrixTileList(const MCInst *MI, unsigned OpNum,
+ const MCSubtargetInfo &STI,
+ raw_ostream &O) {
+ unsigned MaxRegs = 8;
+ unsigned RegMask = MI->getOperand(OpNum).getImm();
+
+ unsigned NumRegs = 0;
+ for (unsigned I = 0; I < MaxRegs; ++I)
+ if ((RegMask & (1 << I)) != 0)
+ ++NumRegs;
+
+ O << "{";
+ unsigned Printed = 0;
+ for (unsigned I = 0; I < MaxRegs; ++I) {
+ unsigned Reg = RegMask & (1 << I);
+ if (Reg == 0)
+ continue;
+ O << getRegisterName(MatrixZADRegisterTable[I]);
+ if (Printed + 1 != NumRegs)
+ O << ", ";
+ ++Printed;
+ }
+ O << "}";
+}
+
void AArch64InstPrinter::printVectorList(const MCInst *MI, unsigned OpNum,
const MCSubtargetInfo &STI,
raw_ostream &O,
diff --git a/llvm/lib/Target/AArch64/MCTargetDesc/AArch64InstPrinter.h b/llvm/lib/Target/AArch64/MCTargetDesc/AArch64InstPrinter.h
index 566a946d521ab..9ec74a1bc7b65 100644
--- a/llvm/lib/Target/AArch64/MCTargetDesc/AArch64InstPrinter.h
+++ b/llvm/lib/Target/AArch64/MCTargetDesc/AArch64InstPrinter.h
@@ -146,6 +146,9 @@ class AArch64InstPrinter : public MCInstPrinter {
const MCSubtargetInfo &STI, raw_ostream &O,
StringRef LayoutSuffix);
+ void printMatrixTileList(const MCInst *MI, unsigned OpNum,
+ const MCSubtargetInfo &STI, raw_ostream &O);
+
/// Print a list of vector registers where the type suffix is implicit
/// (i.e. attached to the instruction rather than the registers).
void printImplicitlyTypedVectorList(const MCInst *MI, unsigned OpNum,
diff --git a/llvm/lib/Target/AArch64/MCTargetDesc/AArch64MCCodeEmitter.cpp b/llvm/lib/Target/AArch64/MCTargetDesc/AArch64MCCodeEmitter.cpp
index 67a8359057218..ad97071434df3 100644
--- a/llvm/lib/Target/AArch64/MCTargetDesc/AArch64MCCodeEmitter.cpp
+++ b/llvm/lib/Target/AArch64/MCTargetDesc/AArch64MCCodeEmitter.cpp
@@ -186,6 +186,9 @@ class AArch64MCCodeEmitter : public MCCodeEmitter {
unsigned fixOneOperandFPComparison(const MCInst &MI, unsigned EncodedValue,
const MCSubtargetInfo &STI) const;
+ uint32_t EncodeMatrixTileListRegisterClass(const MCInst &MI, unsigned OpIdx,
+ SmallVectorImpl<MCFixup> &Fixups,
+ const MCSubtargetInfo &STI) const;
uint32_t encodeMatrixIndexGPR32(const MCInst &MI, unsigned OpIdx,
SmallVectorImpl<MCFixup> &Fixups,
const MCSubtargetInfo &STI) const;
@@ -520,6 +523,14 @@ AArch64MCCodeEmitter::getVecShiftL8OpValue(const MCInst &MI, unsigned OpIdx,
return MO.getImm() - 8;
}
+uint32_t AArch64MCCodeEmitter::EncodeMatrixTileListRegisterClass(
+ const MCInst &MI, unsigned OpIdx, SmallVectorImpl<MCFixup> &Fixups,
+ const MCSubtargetInfo &STI) const {
+ unsigned RegMask = MI.getOperand(OpIdx).getImm();
+ assert(RegMask <= 0xFF && "Invalid register mask!");
+ return RegMask;
+}
+
uint32_t
AArch64MCCodeEmitter::encodeMatrixIndexGPR32(const MCInst &MI, unsigned OpIdx,
SmallVectorImpl<MCFixup> &Fixups,
diff --git a/llvm/lib/Target/AArch64/SMEInstrFormats.td b/llvm/lib/Target/AArch64/SMEInstrFormats.td
index 6dee95edda5db..62089166f4b75 100644
--- a/llvm/lib/Target/AArch64/SMEInstrFormats.td
+++ b/llvm/lib/Target/AArch64/SMEInstrFormats.td
@@ -653,6 +653,38 @@ multiclass sme_tile_to_vector<string mnemonic> {
defm _V : sme_tile_to_vector_v<mnemonic, /*is_col=*/0b1>;
}
+//===----------------------------------------------------------------------===//
+// SME Zero
+//===----------------------------------------------------------------------===//
+
+class sme_zero_inst<string mnemonic>
+ : I<(outs MatrixTileList:$imm), (ins),
+ mnemonic, "\t$imm", "", []>, Sched<[]> {
+ bits<8> imm;
+ let Inst{31-8} = 0b110000000000100000000000;
+ let Inst{7-0} = imm;
+}
+
+multiclass sme_zero<string mnemonic> {
+ def NAME : sme_zero_inst<mnemonic>;
+
+ def : InstAlias<"zero\t\\{za\\}", (!cast<Instruction>(NAME) 0b11111111), 1>;
+ def : InstAlias<"zero\t\\{za0.h\\}", (!cast<Instruction>(NAME) 0b01010101), 1>;
+ def : InstAlias<"zero\t\\{za1.h\\}", (!cast<Instruction>(NAME) 0b10101010), 1>;
+ def : InstAlias<"zero\t\\{za0.s\\}", (!cast<Instruction>(NAME) 0b00010001), 1>;
+ def : InstAlias<"zero\t\\{za1.s\\}", (!cast<Instruction>(NAME) 0b00100010), 1>;
+ def : InstAlias<"zero\t\\{za2.s\\}", (!cast<Instruction>(NAME) 0b01000100), 1>;
+ def : InstAlias<"zero\t\\{za3.s\\}", (!cast<Instruction>(NAME) 0b10001000), 1>;
+ def : InstAlias<"zero\t\\{za0.s,za1.s\\}", (!cast<Instruction>(NAME) 0b00110011), 1>;
+ def : InstAlias<"zero\t\\{za0.s,za3.s\\}", (!cast<Instruction>(NAME) 0b10011001), 1>;
+ def : InstAlias<"zero\t\\{za1.s,za2.s\\}", (!cast<Instruction>(NAME) 0b01100110), 1>;
+ def : InstAlias<"zero\t\\{za2.s,za3.s\\}", (!cast<Instruction>(NAME) 0b11001100), 1>;
+ def : InstAlias<"zero\t\\{za0.s,za1.s,za2.s\\}", (!cast<Instruction>(NAME) 0b01110111), 1>;
+ def : InstAlias<"zero\t\\{za0.s,za1.s,za3.s\\}", (!cast<Instruction>(NAME) 0b10111011), 1>;
+ def : InstAlias<"zero\t\\{za0.s,za2.s,za3.s\\}", (!cast<Instruction>(NAME) 0b11011101), 1>;
+ def : InstAlias<"zero\t\\{za1.s,za2.s,za3.s\\}", (!cast<Instruction>(NAME) 0b11101110), 1>;
+}
+
//===----------------------------------------------------------------------===//
// SVE2 Instructions
//===----------------------------------------------------------------------===//
diff --git a/llvm/test/MC/AArch64/SME/zero-diagnostics.s b/llvm/test/MC/AArch64/SME/zero-diagnostics.s
new file mode 100644
index 0000000000000..44a3e462bbb78
--- /dev/null
+++ b/llvm/test/MC/AArch64/SME/zero-diagnostics.s
@@ -0,0 +1,82 @@
+// RUN: not llvm-mc -triple=aarch64 -show-encoding -mattr=+sme 2>&1 < %s| FileCheck %s
+
+// --------------------------------------------------------------------------//
+// Registers list not in ascending order
+
+zero {za1.s, za0.s}
+// CHECK: [[@LINE-1]]:{{[0-9]+}}: warning: tile list not in ascending order
+// CHECK-NEXT: zero {za1.s, za0.s}
+// CHECK-NEXT: ^
+
+zero {za0.d, za1.d, za4.d, za3.d}
+// CHECK: [[@LINE-1]]:{{[0-9]+}}: warning: tile list not in ascending order
+// CHECK-NEXT: zero {za0.d, za1.d, za4.d, za3.d}
+// CHECK-NEXT: ^
+
+// --------------------------------------------------------------------------//
+// Duplicate tile
+
+zero {za0.s, za0.s}
+// CHECK: [[@LINE-1]]:{{[0-9]+}}: warning: duplicate tile in list
+// CHECK-NEXT: zero {za0.s, za0.s}
+// CHECK-NEXT: ^
+
+zero {za0.d, za1.d, za2.d, za2.d, za3.d}
+// CHECK: [[@LINE-1]]:{{[0-9]+}}: warning: duplicate tile in list
+// CHECK-NEXT: zero {za0.d, za1.d, za2.d, za2.d, za3.d}
+// CHECK-NEXT: ^
+
+// --------------------------------------------------------------------------//
+// Mismatched register size suffix
+
+zero {za0.b, za5.d}
+// CHECK: [[@LINE-1]]:{{[0-9]+}}: error: mismatched register size suffix
+// CHECK-NEXT: zero {za0.b, za5.d}
+// CHECK-NOT: [[@LINE-1]]:{{[0-9]+}}:
+
+// --------------------------------------------------------------------------//
+// Missing '}'
+
+zero {za
+// CHECK: [[@LINE-1]]:{{[0-9]+}}: error: '}' expected
+// CHECK-NEXT: zero {za
+// CHECK-NEXT: ^
+// CHECK-NOT: [[@LINE-1]]:{{[0-9]+}}:
+
+// --------------------------------------------------------------------------//
+// Invalid matrix tile
+
+zero {za0.b, za1.b}
+// CHECK: [[@LINE-1]]:{{[0-9]+}}: error: invalid operand for instruction
+// CHECK-NEXT: zero {za0.b, za1.b}
+// CHECK-NOT: [[@LINE-1]]:{{[0-9]+}}:
+
+zero {za2.h}
+// CHECK: [[@LINE-1]]:{{[0-9]+}}: error: invalid operand for instruction
+// CHECK-NEXT: zero {za2.h}
+// CHECK-NOT: [[@LINE-1]]:{{[0-9]+}}:
+
+zero {za0.s, za1.s, za2.s, za3.s, za4.s}
+// CHECK: [[@LINE-1]]:{{[0-9]+}}: error: invalid operand for instruction
+// CHECK-NEXT: zero {za0.s, za1.s, za2.s, za3.s, za4.s}
+// CHECK-NOT: [[@LINE-1]]:{{[0-9]+}}:
+
+zero {za0.d, za1.d, za2.d, za3.d, za4.d, za5.d, za6.d, za7.d, za8.d}
+// CHECK: [[@LINE-1]]:{{[0-9]+}}: error: invalid operand for instruction
+// CHECK-NEXT: zero {za0.d, za1.d, za2.d, za3.d, za4.d, za5.d, za6.d, za7.d, za8.d}
+// CHECK-NOT: [[@LINE-1]]:{{[0-9]+}}:
+
+zero {za0h.b}
+// CHECK: [[@LINE-1]]:{{[0-9]+}}: error: invalid operand for instruction
+// CHECK-NEXT: zero {za0h.b}
+// CHECK-NOT: [[@LINE-1]]:{{[0-9]+}}:
+
+zero {za0.s, za1h.s}
+// CHECK: [[@LINE-1]]:{{[0-9]+}}: error: invalid operand for instruction
+// CHECK-NEXT: zero {za0.s, za1h.s}
+// CHECK-NOT: [[@LINE-1]]:{{[0-9]+}}:
+
+zero {za15.q}
+// CHECK: [[@LINE-1]]:{{[0-9]+}}: error: invalid operand for instruction
+// CHECK-NEXT: zero {za15.q}
+// CHECK-NOT: [[@LINE-1]]:{{[0-9]+}}:
diff --git a/llvm/test/MC/AArch64/SME/zero.s b/llvm/test/MC/AArch64/SME/zero.s
new file mode 100644
index 0000000000000..c78b22352033b
--- /dev/null
+++ b/llvm/test/MC/AArch64/SME/zero.s
@@ -0,0 +1,250 @@
+// RUN: llvm-mc -triple=aarch64 -show-encoding -mattr=+sme < %s \
+// RUN: | FileCheck %s --check-prefixes=CHECK-ENCODING,CHECK-INST
+// RUN: not llvm-mc -triple=aarch64 -show-encoding < %s 2>&1 \
+// RUN: | FileCheck %s --check-prefix=CHECK-ERROR
+// RUN: llvm-mc -triple=aarch64 -filetype=obj -mattr=+sme < %s \
+// RUN: | llvm-objdump -d --mattr=+sme - | FileCheck %s --check-prefix=CHECK-INST
+// RUN: llvm-mc -triple=aarch64 -filetype=obj -mattr=+sme < %s \
+// RUN: | llvm-objdump -d - | FileCheck %s --check-prefix=CHECK-UNKNOWN
+// Disassemble encoding and check the re-encoding (-show-encoding) matches.
+// RUN: llvm-mc -triple=aarch64 -show-encoding -mattr=+sme < %s \
+// RUN: | sed '/.text/d' | sed 's/.*encoding: //g' \
+// RUN: | llvm-mc -triple=aarch64 -mattr=+sme -disassemble -show-encoding \
+// RUN: | FileCheck %s --check-prefixes=CHECK-ENCODING,CHECK-INST
+
+zero {}
+// CHECK-INST: zero {}
+// CHECK-ENCODING: [0x00,0x00,0x08,0xc0]
+// CHECK-ERROR: instruction requires: sme
+// CHECK-UNKNOWN: 00 00 08 c0 <unknown>
+
+zero {za0.d, za2.d, za4.d, za6.d}
+// CHECK-INST: zero {za0.h}
+// CHECK-ENCODING: [0x55,0x00,0x08,0xc0]
+// CHECK-ERROR: instruction requires: sme
+// CHECK-UNKNOWN: 55 00 08 c0 <unknown>
+
+zero {za0.d, za1.d, za2.d, za4.d, za5.d, za7.d}
+// CHECK-INST: zero {za0.d, za1.d, za2.d, za4.d, za5.d, za7.d}
+// CHECK-ENCODING: [0xb7,0x00,0x08,0xc0]
+// CHECK-ERROR: instruction requires: sme
+// CHECK-UNKNOWN: b7 00 08 c0 <unknown>
+
+zero {za0.d, za1.d, za2.d, za3.d, za4.d, za5.d, za6.d, za7.d}
+// CHECK-INST: zero {za}
+// CHECK-ENCODING: [0xff,0x00,0x08,0xc0]
+// CHECK-ERROR: instruction requires: sme
+// CHECK-UNKNOWN: ff 00 08 c0 <unknown>
+
+// --------------------------------------------------------------------------//
+// Aliases
+
+zero {za}
+// CHECK-INST: zero {za}
+// CHECK-ENCODING: [0xff,0x00,0x08,0xc0]
+// CHECK-ERROR: instruction requires: sme
+// CHECK-UNKNOWN: ff 00 08 c0 <unknown>
+
+zero {za0.b}
+// CHECK-INST: zero {za}
+// CHECK-ENCODING: [0xff,0x00,0x08,0xc0]
+// CHECK-ERROR: instruction requires: sme
+// CHECK-UNKNOWN: ff 00 08 c0 <unknown>
+
+zero {za0.h}
+// CHECK-INST: zero {za0.h}
+// CHECK-ENCODING: [0x55,0x00,0x08,0xc0]
+// CHECK-ERROR: instruction requires: sme
+// CHECK-UNKNOWN: 55 00 08 c0 <unknown>
+
+zero {za1.h}
+// CHECK-INST: zero {za1.h}
+// CHECK-ENCODING: [0xaa,0x00,0x08,0xc0]
+// CHECK-ERROR: instruction requires: sme
+// CHECK-UNKNOWN: aa 00 08 c0 <unknown>
+
+zero {za0.h,za1.h}
+// CHECK-INST: zero {za}
+// CHECK-ENCODING: [0xff,0x00,0x08,0xc0]
+// CHECK-ERROR: instruction requires: sme
+// CHECK-UNKNOWN: ff 00 08 c0 <unknown>
+
+zero {za0.s}
+// CHECK-INST: zero {za0.s}
+// CHECK-ENCODING: [0x11,0x00,0x08,0xc0]
+// CHECK-ERROR: instruction requires: sme
+// CHECK-UNKNOWN: 11 00 08 c0 <unknown>
+
+zero {za1.s}
+// CHECK-INST: zero {za1.s}
+// CHECK-ENCODING: [0x22,0x00,0x08,0xc0]
+// CHECK-ERROR: instruction requires: sme
+// CHECK-UNKNOWN: 22 00 08 c0 <unknown>
+
+zero {za2.s}
+// CHECK-INST: zero {za2.s}
+// CHECK-ENCODING: [0x44,0x00,0x08,0xc0]
+// CHECK-ERROR: instruction requires: sme
+// CHECK-UNKNOWN: 44 00 08 c0 <unknown>
+
+zero {za3.s}
+// CHECK-INST: zero {za3.s}
+// CHECK-ENCODING: [0x88,0x00,0x08,0xc0]
+// CHECK-ERROR: instruction requires: sme
+// CHECK-UNKNOWN: 88 00 08 c0 <unknown>
+
+zero {za0.s,za1.s}
+// CHECK-INST: zero {za0.s,za1.s}
+// CHECK-ENCODING: [0x33,0x00,0x08,0xc0]
+// CHECK-ERROR: instruction requires: sme
+// CHECK-UNKNOWN: 33 00 08 c0 <unknown>
+
+zero {za0.s,za2.s}
+// CHECK-INST: zero {za0.h}
+// CHECK-ENCODING: [0x55,0x00,0x08,0xc0]
+// CHECK-ERROR: instruction requires: sme
+// CHECK-UNKNOWN: 55 00 08 c0 <unknown>
+
+zero {za0.s,za3.s}
+// CHECK-INST: zero {za0.s,za3.s}
+// CHECK-ENCODING: [0x99,0x00,0x08,0xc0]
+// CHECK-ERROR: instruction requires: sme
+// CHECK-UNKNOWN: 99 00 08 c0 <unknown>
+
+zero {za1.s,za2.s}
+// CHECK-INST: zero {za1.s,za2.s}
+// CHECK-ENCODING: [0x66,0x00,0x08,0xc0]
+// CHECK-ERROR: instruction requires: sme
+// CHECK-UNKNOWN: 66 00 08 c0 <unknown>
+
+zero {za1.s,za3.s}
+// CHECK-INST: zero {za1.h}
+// CHECK-ENCODING: [0xaa,0x00,0x08,0xc0]
+// CHECK-ERROR: instruction requires: sme
+// CHECK-UNKNOWN: aa 00 08 c0 <unknown>
+
+zero {za2.s,za3.s}
+// CHECK-INST: zero {za2.s,za3.s}
+// CHECK-ENCODING: [0xcc,0x00,0x08,0xc0]
+// CHECK-ERROR: instruction requires: sme
+// CHECK-UNKNOWN: cc 00 08 c0 <unknown>
+
+zero {za0.s,za1.s,za2.s}
+// CHECK-INST: zero {za0.s,za1.s,za2.s}
+// CHECK-ENCODING: [0x77,0x00,0x08,0xc0]
+// CHECK-ERROR: instruction requires: sme
+// CHECK-UNKNOWN: 77 00 08 c0 <unknown>
+
+zero {za0.s,za1.s,za3.s}
+// CHECK-INST: zero {za0.s,za1.s,za3.s}
+// CHECK-ENCODING: [0xbb,0x00,0x08,0xc0]
+// CHECK-ERROR: instruction requires: sme
+// CHECK-UNKNOWN: bb 00 08 c0 <unknown>
+
+zero {za0.s,za2.s,za3.s}
+// CHECK-INST: zero {za0.s,za2.s,za3.s}
+// CHECK-ENCODING: [0xdd,0x00,0x08,0xc0]
+// CHECK-ERROR: instruction requires: sme
+// CHECK-UNKNOWN: dd 00 08 c0 <unknown>
+
+zero {za1.s,za2.s,za3.s}
+// CHECK-INST: zero {za1.s,za2.s,za3.s}
+// CHECK-ENCODING: [0xee,0x00,0x08,0xc0]
+// CHECK-ERROR: instruction requires: sme
+// CHECK-UNKNOWN: ee 00 08 c0 <unknown>
+
+zero {za0.s,za1.s,za2.s,za3.s}
+// CHECK-INST: zero {za}
+// CHECK-ENCODING: [0xff,0x00,0x08,0xc0]
+// CHECK-ERROR: instruction requires: sme
+// CHECK-UNKNOWN: ff 00 08 c0 <unknown>
+
+zero {za0.d,za1.d,za2.d,za3.d,za4.d,za5.d,za6.d,za7.d}
+// CHECK-INST: zero {za}
+// CHECK-ENCODING: [0xff,0x00,0x08,0xc0]
+// CHECK-ERROR: instruction requires: sme
+// CHECK-UNKNOWN: ff 00 08 c0 <unknown>
+
+zero {za0.d,za2.d,za4.d,za6.d}
+// CHECK-INST: zero {za0.h}
+// CHECK-ENCODING: [0x55,0x00,0x08,0xc0]
+// CHECK-ERROR: instruction requires: sme
+// CHECK-UNKNOWN: 55 00 08 c0 <unknown>
+
+zero {za1.d,za3.d,za5.d,za7.d}
+// CHECK-INST: zero {za1.h}
+// CHECK-ENCODING: [0xaa,0x00,0x08,0xc0]
+// CHECK-ERROR: instruction requires: sme
+// CHECK-UNKNOWN: aa 00 08 c0 <unknown>
+
+zero {za0.d,za4.d}
+// CHECK-INST: zero {za0.s}
+// CHECK-ENCODING: [0x11,0x00,0x08,0xc0]
+// CHECK-ERROR: instruction requires: sme
+// CHECK-UNKNOWN: 11 00 08 c0 <unknown>
+
+zero {za1.d,za5.d}
+// CHECK-INST: zero {za1.s}
+// CHECK-ENCODING: [0x22,0x00,0x08,0xc0]
+// CHECK-ERROR: instruction requires: sme
+// CHECK-UNKNOWN: 22 00 08 c0 <unknown>
+
+zero {za2.d,za6.d}
+// CHECK-INST: zero {za2.s}
+// CHECK-ENCODING: [0x44,0x00,0x08,0xc0]
+// CHECK-ERROR: instruction requires: sme
+// CHECK-UNKNOWN: 44 00 08 c0 <unknown>
+
+zero {za3.d,za7.d}
+// CHECK-INST: zero {za3.s}
+// CHECK-ENCODING: [0x88,0x00,0x08,0xc0]
+// CHECK-ERROR: instruction requires: sme
+// CHECK-UNKNOWN: 88 00 08 c0 <unknown>
+
+zero {za0.d,za1.d,za4.d,za5.d}
+// CHECK-INST: zero {za0.s,za1.s}
+// CHECK-ENCODING: [0x33,0x00,0x08,0xc0]
+// CHECK-ERROR: instruction requires: sme
+// CHECK-UNKNOWN: 33 00 08 c0 <unknown>
+
+zero {za0.d,za3.d,za4.d,za7.d}
+// CHECK-INST: zero {za0.s,za3.s}
+// CHECK-ENCODING: [0x99,0x00,0x08,0xc0]
+// CHECK-ERROR: instruction requires: sme
+// CHECK-UNKNOWN: 99 00 08 c0 <unknown>
+
+zero {za1.d,za2.d,za5.d,za6.d}
+// CHECK-INST: zero {za1.s,za2.s}
+// CHECK-ENCODING: [0x66,0x00,0x08,0xc0]
+// CHECK-ERROR: instruction requires: sme
+// CHECK-UNKNOWN: 66 00 08 c0 <unknown>
+
+zero {za2.d,za3.d,za6.d,za7.d}
+// CHECK-INST: zero {za2.s,za3.s}
+// CHECK-ENCODING: [0xcc,0x00,0x08,0xc0]
+// CHECK-ERROR: instruction requires: sme
+// CHECK-UNKNOWN: cc 00 08 c0 <unknown>
+
+zero {za0.d,za1.d,za2.d,za4.d,za5.d,za6.d}
+// CHECK-INST: zero {za0.s,za1.s,za2.s}
+// CHECK-ENCODING: [0x77,0x00,0x08,0xc0]
+// CHECK-ERROR: instruction requires: sme
+// CHECK-UNKNOWN: 77 00 08 c0 <unknown>
+
+zero {za0.d,za1.d,za3.d,za4.d,za5.d,za7.d}
+// CHECK-INST: zero {za0.s,za1.s,za3.s}
+// CHECK-ENCODING: [0xbb,0x00,0x08,0xc0]
+// CHECK-ERROR: instruction requires: sme
+// CHECK-UNKNOWN: bb 00 08 c0 <unknown>
+
+zero {za0.d,za2.d,za3.d,za4.d,za6.d,za7.d}
+// CHECK-INST: zero {za0.s,za2.s,za3.s}
+// CHECK-ENCODING: [0xdd,0x00,0x08,0xc0]
+// CHECK-ERROR: instruction requires: sme
+// CHECK-UNKNOWN: dd 00 08 c0 <unknown>
+
+zero {za1.d,za2.d,za3.d,za5.d,za6.d,za7.d}
+// CHECK-INST: zero {za1.s,za2.s,za3.s}
+// CHECK-ENCODING: [0xee,0x00,0x08,0xc0]
+// CHECK-ERROR: instruction requires: sme
+// CHECK-UNKNOWN: ee 00 08 c0 <unknown>
More information about the llvm-commits
mailing list