let ParserMethod = "tryParseSVEPredicateVector<RegKind::SVEPredicateAsCounter>";
}
+class PNRRegOp<string Suffix, AsmOperandClass C, int EltSize, RegisterClass RC>
+ : PPRRegOp<Suffix, C, ElementSizeNone, RC> {
+ let PrintMethod = "printPredicateAsCounter<" # EltSize # ">";
+}
+
+def PNRAsmOp8 : PNRAsmOperand<"PNPredicateB", "PPR", 8>;
+def PNRAsmOp16 : PNRAsmOperand<"PNPredicateH", "PPR", 16>;
+def PNRAsmOp32 : PNRAsmOperand<"PNPredicateS", "PPR", 32>;
+def PNRAsmOp64 : PNRAsmOperand<"PNPredicateD", "PPR", 64>;
+
+def PNR8 : PNRRegOp<"b", PNRAsmOp8, 8, PPR>;
+def PNR16 : PNRRegOp<"h", PNRAsmOp16, 16, PPR>;
+def PNR32 : PNRRegOp<"s", PNRAsmOp32, 32, PPR>;
+def PNR64 : PNRRegOp<"d", PNRAsmOp64, 64, PPR>;
+
class PNRP8to15RegOp<string Suffix, AsmOperandClass C, int EltSize, RegisterClass RC>
: PPRRegOp<Suffix, C, ElementSizeNone, RC> {
let PrintMethod = "printPredicateAsCounter<" # EltSize # ">";
def SDOT_ZZZI_HtoS : sve2p1_two_way_dot_vvi<"sdot", 0b0>;
def UDOT_ZZZI_HtoS : sve2p1_two_way_dot_vvi<"udot", 0b1>;
+defm CNTP_XCI : sve2p1_pcount_pn<"cntp", 0b000>;
defm PEXT_PCI : sve2p1_pred_as_ctr_to_mask<"pext">;
defm PTRUE_C : sve2p1_ptrue_pn<"ptrue">;
def : SVEPREDPAT<"all", 0x1f>;
//===----------------------------------------------------------------------===//
+// SVE Predicate-as-counter patterns
+//===----------------------------------------------------------------------===//
+
+class SVEVECLENSPECIFIER<string name, bits<1> encoding> : SearchableTable {
+ let SearchableFields = ["Name", "Encoding"];
+ let EnumValueField = "Encoding";
+
+ string Name = name;
+ bits<1> Encoding;
+ let Encoding = encoding;
+}
+
+def : SVEVECLENSPECIFIER<"vlx2", 0x0>;
+def : SVEVECLENSPECIFIER<"vlx4", 0x1>;
+
+//===----------------------------------------------------------------------===//
// Exact FP Immediates.
//
// These definitions are used to create a lookup table with FP Immediates that
bool ExpectMatch = false);
OperandMatchResultTy tryParseMatrixTileList(OperandVector &Operands);
OperandMatchResultTy tryParseSVEPattern(OperandVector &Operands);
+ OperandMatchResultTy tryParseSVEVecLenSpecifier(OperandVector &Operands);
OperandMatchResultTy tryParseGPR64x8(OperandVector &Operands);
OperandMatchResultTy tryParseImmRange(OperandVector &Operands);
return DiagnosticPredicateTy::NearMatch;
}
+ DiagnosticPredicate isSVEVecLenSpecifier() const {
+ if (!isImm())
+ return DiagnosticPredicateTy::NoMatch;
+ auto *MCE = dyn_cast<MCConstantExpr>(getImm());
+ if (!MCE)
+ return DiagnosticPredicateTy::NoMatch;
+ int64_t Val = MCE->getValue();
+ if (Val >= 0 && Val <= 1)
+ return DiagnosticPredicateTy::Match;
+ return DiagnosticPredicateTy::NearMatch;
+ }
+
bool isSymbolicUImm12Offset(const MCExpr *Expr) const {
AArch64MCExpr::VariantKind ELFRefKind;
MCSymbolRefExpr::VariantKind DarwinRefKind;
case Match_InvalidSVEPNPredicateAny_p8to15Reg:
return Error(Loc, "invalid restricted predicate-as-counter register "
"expected pn8..pn15");
+ case Match_InvalidSVEPNPredicateBReg:
+ case Match_InvalidSVEPNPredicateHReg:
+ case Match_InvalidSVEPNPredicateSReg:
+ case Match_InvalidSVEPNPredicateDReg:
+ return Error(Loc, "Invalid predicate register, expected PN in range "
+ "pn0..pn15 with element suffix.");
+ case Match_InvalidSVEVecLenSpecifier:
+ return Error(Loc, "Invalid vector length specifier, expected VLx2 or VLx4");
case Match_InvalidSVEExactFPImmOperandHalfOne:
return Error(Loc, "Invalid floating point constant, expected 0.5 or 1.0.");
case Match_InvalidSVEExactFPImmOperandHalfTwo:
case Match_InvalidZPR_4b64:
case Match_InvalidSVEPredicateAnyReg:
case Match_InvalidSVEPattern:
+ case Match_InvalidSVEVecLenSpecifier:
case Match_InvalidSVEPredicateBReg:
case Match_InvalidSVEPredicateHReg:
case Match_InvalidSVEPredicateSReg:
case Match_InvalidSVEPNPredicateS_p8to15Reg:
case Match_InvalidSVEPNPredicateD_p8to15Reg:
case Match_InvalidSVEPNPredicateAny_p8to15Reg:
+ case Match_InvalidSVEPNPredicateBReg:
+ case Match_InvalidSVEPNPredicateHReg:
+ case Match_InvalidSVEPNPredicateSReg:
+ case Match_InvalidSVEPNPredicateDReg:
case Match_InvalidSVEExactFPImmOperandHalfOne:
case Match_InvalidSVEExactFPImmOperandHalfTwo:
case Match_InvalidSVEExactFPImmOperandZeroOne:
}
OperandMatchResultTy
+AArch64AsmParser::tryParseSVEVecLenSpecifier(OperandVector &Operands) {
+ int64_t Pattern;
+ SMLoc SS = getLoc();
+ const AsmToken &TokE = getTok();
+ // Parse the pattern
+ auto Pat = AArch64SVEVecLenSpecifier::lookupSVEVECLENSPECIFIERByName(
+ TokE.getString());
+ if (!Pat)
+ return MatchOperand_NoMatch;
+
+ Lex();
+ Pattern = Pat->Encoding;
+ assert(Pattern >= 0 && Pattern <= 1 && "Pattern does not exist");
+
+ Operands.push_back(
+ AArch64Operand::CreateImm(MCConstantExpr::create(Pattern, getContext()),
+ SS, getLoc(), getContext()));
+
+ return MatchOperand_Success;
+}
+
+OperandMatchResultTy
AArch64AsmParser::tryParseGPR64x8(OperandVector &Operands) {
SMLoc SS = getLoc();
O << markup("<imm:") << '#' << formatImm(Val) << markup(">");
}
+void AArch64InstPrinter::printSVEVecLenSpecifier(const MCInst *MI,
+ unsigned OpNum,
+ const MCSubtargetInfo &STI,
+ raw_ostream &O) {
+ unsigned Val = MI->getOperand(OpNum).getImm();
+ // Pattern has only 1 bit
+ if (Val > 1)
+ llvm_unreachable("Invalid vector length specifier");
+ if (auto Pat =
+ AArch64SVEVecLenSpecifier::lookupSVEVECLENSPECIFIERByEncoding(Val))
+ O << Pat->Name;
+ else
+ llvm_unreachable("Invalid vector length specifier");
+}
+
template <char suffix>
void AArch64InstPrinter::printSVERegOp(const MCInst *MI, unsigned OpNum,
const MCSubtargetInfo &STI,
const MCSubtargetInfo &STI, raw_ostream &O);
void printSVEPattern(const MCInst *MI, unsigned OpNum,
const MCSubtargetInfo &STI, raw_ostream &O);
+ void printSVEVecLenSpecifier(const MCInst *MI, unsigned OpNum,
+ const MCSubtargetInfo &STI, raw_ostream &O);
template <bool IsVertical>
void printMatrixTileVector(const MCInst *MI, unsigned OpNum,
let ParserMatchClass = SVEPatternOperand;
}
+def SVEVecLenSpecifierOperand : AsmOperandClass {
+ let Name = "SVEVecLenSpecifier";
+ let ParserMethod = "tryParseSVEVecLenSpecifier";
+ let PredicateMethod = "isSVEVecLenSpecifier";
+ let RenderMethod = "addImmOperands";
+ let DiagnosticType = "InvalidSVEVecLenSpecifier";
+}
+
+def sve_vec_len_specifier_enum : Operand<i32>, TImmLeaf<i32, [{
+ return (((uint32_t)Imm) < 2);
+ }]> {
+
+ let PrintMethod = "printSVEVecLenSpecifier";
+ let ParserMatchClass = SVEVecLenSpecifierOperand;
+}
+
def SVEPrefetchOperand : AsmOperandClass {
let Name = "SVEPrefetch";
let ParserMethod = "tryParsePrefetch<true>";
def : InstAlias<mnemonic # " $Zt, $PNg, [$Rn]",
(!cast<Instruction>(NAME) vector_ty:$Zt, PNRAny_p8to15:$PNg, GPR64sp:$Rn,0), 1>;
}
+
+// SVE predicate count (predicate-as-counter)
+class sve2p1_pcount_pn<string mnemonic, bits<3> opc, bits<2> sz, PNRRegOp pnrty>
+ : I<(outs GPR64:$Rd),
+ (ins pnrty:$PNn, sve_vec_len_specifier_enum:$vl),
+ mnemonic, "\t$Rd, $PNn, $vl",
+ "", []>, Sched<[]> {
+ bits<5> Rd;
+ bits<4> PNn;
+ bits<1> vl;
+ let Inst{31-24} = 0b00100101;
+ let Inst{23-22} = sz;
+ let Inst{21-19} = 0b100;
+ let Inst{18-16} = opc;
+ let Inst{15-11} = 0b10000;
+ let Inst{10} = vl;
+ let Inst{9} = 0b1;
+ let Inst{8-5} = PNn;
+ let Inst{4-0} = Rd;
+}
+
+multiclass sve2p1_pcount_pn<string mnemonic, bits<3> opc> {
+ def _B : sve2p1_pcount_pn<mnemonic, opc, 0b00, PNR8>;
+ def _H : sve2p1_pcount_pn<mnemonic, opc, 0b01, PNR16>;
+ def _S : sve2p1_pcount_pn<mnemonic, opc, 0b10, PNR32>;
+ def _D : sve2p1_pcount_pn<mnemonic, opc, 0b11, PNR64>;
+}
}
namespace llvm {
+namespace AArch64SVEVecLenSpecifier {
+#define GET_SVEVECLENSPECIFIER_IMPL
+#include "AArch64GenSystemOperands.inc"
+} // namespace AArch64SVEVecLenSpecifier
+} // namespace llvm
+
+namespace llvm {
namespace AArch64ExactFPImm {
#define GET_EXACTFPIMM_IMPL
#include "AArch64GenSystemOperands.inc"
#include "AArch64GenSystemOperands.inc"
}
+namespace AArch64SVEVecLenSpecifier {
+ struct SVEVECLENSPECIFIER {
+ const char *Name;
+ uint16_t Encoding;
+ };
+#define GET_SVEVECLENSPECIFIER_DECL
+#include "AArch64GenSystemOperands.inc"
+} // namespace AArch64SVEVecLenSpecifier
+
/// Return the number of active elements for VL1 to VL256 predicate pattern,
/// zero for all other patterns.
inline unsigned getNumElementsFromSVEPredPattern(unsigned Pattern) {
--- /dev/null
+// RUN: not llvm-mc -triple=aarch64 -show-encoding -mattr=+sve2p1 2>&1 < %s | FileCheck %s
+
+// --------------------------------------------------------------------------//
+// Invalid Pattern
+
+cntp x0, pn0.s, vlx1
+// CHECK: [[@LINE-1]]:{{[0-9]+}}: error: invalid operand
+// CHECK-NEXT: cntp x0, pn0.s, vlx1
+// CHECK-NOT: [[@LINE-1]]:{{[0-9]+}}:
+
+// --------------------------------------------------------------------------//
+// Invalid use of predicate without suffix
+
+cntp x0, pn0, vlx2
+// CHECK: [[@LINE-1]]:{{[0-9]+}}: error: Invalid predicate register, expected PN in range pn0..pn15 with element suffix.
+// CHECK-NEXT: cntp x0, pn0, vlx2
+// CHECK-NOT: [[@LINE-1]]:{{[0-9]+}}:
+
+// --------------------------------------------------------------------------//
+// Invalid destination register type
+
+cntp w0, pn0.b, vlx2
+// CHECK: [[@LINE-1]]:{{[0-9]+}}: error: invalid operand for instruction
+// CHECK-NEXT: cntp w0, pn0.b, vlx2
+// CHECK-NOT: [[@LINE-1]]:{{[0-9]+}}:
+
--- /dev/null
+// RUN: llvm-mc -triple=aarch64 -show-encoding -mattr=+sme2 < %s \
+// RUN: | FileCheck %s --check-prefixes=CHECK-ENCODING,CHECK-INST
+// RUN: llvm-mc -triple=aarch64 -show-encoding -mattr=+sve2p1 < %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=+sme2 < %s \
+// RUN: | llvm-objdump -d --mattr=+sme2 - | FileCheck %s --check-prefix=CHECK-INST
+// RUN: llvm-mc -triple=aarch64 -filetype=obj -mattr=+sme2 < %s \
+// RUN: | llvm-objdump -d - | FileCheck %s --check-prefix=CHECK-UNKNOWN
+// RUN: llvm-mc -triple=aarch64 -show-encoding -mattr=+sme2 < %s \
+// RUN: | sed '/.text/d' | sed 's/.*encoding: //g' \
+// RUN: | llvm-mc -triple=aarch64 -mattr=+sme2 -disassemble -show-encoding \
+// RUN: | FileCheck %s --check-prefixes=CHECK-ENCODING,CHECK-INST
+
+cntp x0, pn0.h, vlx2 // 00100101-01100000-10000010-00000000
+// CHECK-INST: cntp x0, pn0.h, vlx2
+// CHECK-ENCODING: [0x00,0x82,0x60,0x25]
+// CHECK-ERROR: instruction requires: sme2 or sve2p1
+// CHECK-UNKNOWN: 25608200 <unknown>
+
+cntp x21, pn10.h, vlx4 // 00100101-01100000-10000111-01010101
+// CHECK-INST: cntp x21, pn10.h, vlx4
+// CHECK-ENCODING: [0x55,0x87,0x60,0x25]
+// CHECK-ERROR: instruction requires: sme2 or sve2p1
+// CHECK-UNKNOWN: 25608755 <unknown>
+
+cntp x23, pn13.h, vlx4 // 00100101-01100000-10000111-10110111
+// CHECK-INST: cntp x23, pn13.h, vlx4
+// CHECK-ENCODING: [0xb7,0x87,0x60,0x25]
+// CHECK-ERROR: instruction requires: sme2 or sve2p1
+// CHECK-UNKNOWN: 256087b7 <unknown>
+
+cntp xzr, pn15.h, vlx4 // 00100101-01100000-10000111-11111111
+// CHECK-INST: cntp xzr, pn15.h, vlx4
+// CHECK-ENCODING: [0xff,0x87,0x60,0x25]
+// CHECK-ERROR: instruction requires: sme2 or sve2p1
+// CHECK-UNKNOWN: 256087ff <unknown>
+
+cntp x0, pn0.s, vlx2 // 00100101-10100000-10000010-00000000
+// CHECK-INST: cntp x0, pn0.s, vlx2
+// CHECK-ENCODING: [0x00,0x82,0xa0,0x25]
+// CHECK-ERROR: instruction requires: sme2 or sve2p1
+// CHECK-UNKNOWN: 25a08200 <unknown>
+
+cntp x21, pn10.s, vlx4 // 00100101-10100000-10000111-01010101
+// CHECK-INST: cntp x21, pn10.s, vlx4
+// CHECK-ENCODING: [0x55,0x87,0xa0,0x25]
+// CHECK-ERROR: instruction requires: sme2 or sve2p1
+// CHECK-UNKNOWN: 25a08755 <unknown>
+
+cntp x23, pn13.s, vlx4 // 00100101-10100000-10000111-10110111
+// CHECK-INST: cntp x23, pn13.s, vlx4
+// CHECK-ENCODING: [0xb7,0x87,0xa0,0x25]
+// CHECK-ERROR: instruction requires: sme2 or sve2p1
+// CHECK-UNKNOWN: 25a087b7 <unknown>
+
+cntp xzr, pn15.s, vlx4 // 00100101-10100000-10000111-11111111
+// CHECK-INST: cntp xzr, pn15.s, vlx4
+// CHECK-ENCODING: [0xff,0x87,0xa0,0x25]
+// CHECK-ERROR: instruction requires: sme2 or sve2p1
+// CHECK-UNKNOWN: 25a087ff <unknown>
+
+cntp x0, pn0.d, vlx2 // 00100101-11100000-10000010-00000000
+// CHECK-INST: cntp x0, pn0.d, vlx2
+// CHECK-ENCODING: [0x00,0x82,0xe0,0x25]
+// CHECK-ERROR: instruction requires: sme2 or sve2p1
+// CHECK-UNKNOWN: 25e08200 <unknown>
+
+cntp x21, pn10.d, vlx4 // 00100101-11100000-10000111-01010101
+// CHECK-INST: cntp x21, pn10.d, vlx4
+// CHECK-ENCODING: [0x55,0x87,0xe0,0x25]
+// CHECK-ERROR: instruction requires: sme2 or sve2p1
+// CHECK-UNKNOWN: 25e08755 <unknown>
+
+cntp x23, pn13.d, vlx4 // 00100101-11100000-10000111-10110111
+// CHECK-INST: cntp x23, pn13.d, vlx4
+// CHECK-ENCODING: [0xb7,0x87,0xe0,0x25]
+// CHECK-ERROR: instruction requires: sme2 or sve2p1
+// CHECK-UNKNOWN: 25e087b7 <unknown>
+
+cntp xzr, pn15.d, vlx4 // 00100101-11100000-10000111-11111111
+// CHECK-INST: cntp xzr, pn15.d, vlx4
+// CHECK-ENCODING: [0xff,0x87,0xe0,0x25]
+// CHECK-ERROR: instruction requires: sme2 or sve2p1
+// CHECK-UNKNOWN: 25e087ff <unknown>
+
+cntp x0, pn0.b, vlx2 // 00100101-00100000-10000010-00000000
+// CHECK-INST: cntp x0, pn0.b, vlx2
+// CHECK-ENCODING: [0x00,0x82,0x20,0x25]
+// CHECK-ERROR: instruction requires: sme2 or sve2p1
+// CHECK-UNKNOWN: 25208200 <unknown>
+
+cntp x21, pn10.b, vlx4 // 00100101-00100000-10000111-01010101
+// CHECK-INST: cntp x21, pn10.b, vlx4
+// CHECK-ENCODING: [0x55,0x87,0x20,0x25]
+// CHECK-ERROR: instruction requires: sme2 or sve2p1
+// CHECK-UNKNOWN: 25208755 <unknown>
+
+cntp x23, pn13.b, vlx4 // 00100101-00100000-10000111-10110111
+// CHECK-INST: cntp x23, pn13.b, vlx4
+// CHECK-ENCODING: [0xb7,0x87,0x20,0x25]
+// CHECK-ERROR: instruction requires: sme2 or sve2p1
+// CHECK-UNKNOWN: 252087b7 <unknown>
+
+cntp xzr, pn15.b, vlx4 // 00100101-00100000-10000111-11111111
+// CHECK-INST: cntp xzr, pn15.b, vlx4
+// CHECK-ENCODING: [0xff,0x87,0x20,0x25]
+// CHECK-ERROR: instruction requires: sme2 or sve2p1
+// CHECK-UNKNOWN: 252087ff <unknown>