summaryrefslogtreecommitdiffstats
path: root/llvm/lib/Target
diff options
context:
space:
mode:
Diffstat (limited to 'llvm/lib/Target')
-rw-r--r--llvm/lib/Target/AArch64/AArch64RegisterInfo.td53
-rw-r--r--llvm/lib/Target/AArch64/AArch64SVEInstrInfo.td6
-rw-r--r--llvm/lib/Target/AArch64/AsmParser/AArch64AsmParser.cpp114
-rw-r--r--llvm/lib/Target/AArch64/Disassembler/AArch64Disassembler.cpp20
-rw-r--r--llvm/lib/Target/AArch64/SVEInstrFormats.td62
5 files changed, 247 insertions, 8 deletions
diff --git a/llvm/lib/Target/AArch64/AArch64RegisterInfo.td b/llvm/lib/Target/AArch64/AArch64RegisterInfo.td
index a9fb0200d80..39e3e33b0d2 100644
--- a/llvm/lib/Target/AArch64/AArch64RegisterInfo.td
+++ b/llvm/lib/Target/AArch64/AArch64RegisterInfo.td
@@ -652,6 +652,24 @@ def XSeqPairClassOperand :
//===----- END: v8.1a atomic CASP register operands -----------------------===//
+// SVE predicate registers
+def P0 : AArch64Reg<0, "p0">, DwarfRegNum<[48]>;
+def P1 : AArch64Reg<1, "p1">, DwarfRegNum<[49]>;
+def P2 : AArch64Reg<2, "p2">, DwarfRegNum<[50]>;
+def P3 : AArch64Reg<3, "p3">, DwarfRegNum<[51]>;
+def P4 : AArch64Reg<4, "p4">, DwarfRegNum<[52]>;
+def P5 : AArch64Reg<5, "p5">, DwarfRegNum<[53]>;
+def P6 : AArch64Reg<6, "p6">, DwarfRegNum<[54]>;
+def P7 : AArch64Reg<7, "p7">, DwarfRegNum<[55]>;
+def P8 : AArch64Reg<8, "p8">, DwarfRegNum<[56]>;
+def P9 : AArch64Reg<9, "p9">, DwarfRegNum<[57]>;
+def P10 : AArch64Reg<10, "p10">, DwarfRegNum<[58]>;
+def P11 : AArch64Reg<11, "p11">, DwarfRegNum<[59]>;
+def P12 : AArch64Reg<12, "p12">, DwarfRegNum<[60]>;
+def P13 : AArch64Reg<13, "p13">, DwarfRegNum<[61]>;
+def P14 : AArch64Reg<14, "p14">, DwarfRegNum<[62]>;
+def P15 : AArch64Reg<15, "p15">, DwarfRegNum<[63]>;
+
// The part of SVE registers that don't overlap Neon registers.
// These are only used as part of clobber lists.
def Z0_HI : AArch64Reg<0, "z0_hi">;
@@ -731,11 +749,43 @@ class SVERegOp <string Suffix, AsmOperandClass C,
let ParserMatchClass = C;
}
+class PPRRegOp <string Suffix, AsmOperandClass C,
+ RegisterClass RC> : SVERegOp<Suffix, C, RC> {}
class ZPRRegOp <string Suffix, AsmOperandClass C,
RegisterClass RC> : SVERegOp<Suffix, C, RC> {}
//******************************************************************************
+// SVE predicate register class.
+def PPR : RegisterClass<"AArch64",
+ [nxv16i1, nxv8i1, nxv4i1, nxv2i1],
+ 16, (sequence "P%u", 0, 15)> {
+ let Size = 16;
+}
+
+class PPRAsmOperand <string name, int Width>: AsmOperandClass {
+ let Name = "SVE" # name # "Reg";
+ let PredicateMethod = "isSVEVectorRegOfWidth<"
+ # Width # ", AArch64::PPRRegClassID>";
+ let DiagnosticType = "InvalidSVE" # name # "Reg";
+ let RenderMethod = "addRegOperands";
+ let ParserMethod = "tryParseSVEPredicateVector";
+}
+
+def PPRAsmOpAny : PPRAsmOperand<"PredicateAny", -1>;
+def PPRAsmOp8 : PPRAsmOperand<"PredicateB", 8>;
+def PPRAsmOp16 : PPRAsmOperand<"PredicateH", 16>;
+def PPRAsmOp32 : PPRAsmOperand<"PredicateS", 32>;
+def PPRAsmOp64 : PPRAsmOperand<"PredicateD", 64>;
+
+def PPRAny : PPRRegOp<"", PPRAsmOpAny, PPR>;
+def PPR8 : PPRRegOp<"b", PPRAsmOp8, PPR>;
+def PPR16 : PPRRegOp<"h", PPRAsmOp16, PPR>;
+def PPR32 : PPRRegOp<"s", PPRAsmOp32, PPR>;
+def PPR64 : PPRRegOp<"d", PPRAsmOp64, PPR>;
+
+//******************************************************************************
+
// SVE vector register class
def ZPR : RegisterClass<"AArch64",
[nxv16i8, nxv8i16, nxv4i32, nxv2i64,
@@ -748,7 +798,8 @@ def ZPR : RegisterClass<"AArch64",
class ZPRAsmOperand <string name, int Width>: AsmOperandClass {
let Name = "SVE" # name # "Reg";
- let PredicateMethod = "isSVEDataVectorRegOfWidth<" # Width # ">";
+ let PredicateMethod = "isSVEVectorRegOfWidth<"
+ # Width # ", AArch64::ZPRRegClassID>";
let RenderMethod = "addRegOperands";
let ParserMethod = "tryParseSVEDataVector<"
# !if(!eq(Width, -1), "false", "true") # ">";
diff --git a/llvm/lib/Target/AArch64/AArch64SVEInstrInfo.td b/llvm/lib/Target/AArch64/AArch64SVEInstrInfo.td
index 7da0b28d22d..bcd7b60875a 100644
--- a/llvm/lib/Target/AArch64/AArch64SVEInstrInfo.td
+++ b/llvm/lib/Target/AArch64/AArch64SVEInstrInfo.td
@@ -14,4 +14,10 @@
let Predicates = [HasSVE] in {
defm ADD_ZZZ : sve_int_bin_cons_arit_0<0b000, "add">;
defm SUB_ZZZ : sve_int_bin_cons_arit_0<0b001, "sub">;
+
+ defm ZIP1_ZZZ : sve_int_perm_bin_perm_zz<0b000, "zip1">;
+ defm ZIP2_ZZZ : sve_int_perm_bin_perm_zz<0b001, "zip2">;
+
+ defm ZIP1_PPP : sve_int_perm_bin_perm_pp<0b000, "zip1">;
+ defm ZIP2_PPP : sve_int_perm_bin_perm_pp<0b001, "zip2">;
}
diff --git a/llvm/lib/Target/AArch64/AsmParser/AArch64AsmParser.cpp b/llvm/lib/Target/AArch64/AsmParser/AArch64AsmParser.cpp
index 83764aab905..6e63783e564 100644
--- a/llvm/lib/Target/AArch64/AsmParser/AArch64AsmParser.cpp
+++ b/llvm/lib/Target/AArch64/AsmParser/AArch64AsmParser.cpp
@@ -59,7 +59,12 @@ using namespace llvm;
namespace {
-enum class RegKind {Scalar, NeonVector, SVEDataVector};
+enum class RegKind {
+ Scalar,
+ NeonVector,
+ SVEDataVector,
+ SVEPredicateVector
+};
class AArch64AsmParser : public MCTargetAsmParser {
private:
@@ -134,6 +139,7 @@ private:
OperandMatchResultTy tryParseGPRSeqPair(OperandVector &Operands);
template <bool ParseSuffix>
OperandMatchResultTy tryParseSVEDataVector(OperandVector &Operands);
+ OperandMatchResultTy tryParseSVEPredicateVector(OperandVector &Operands);
public:
enum AArch64MatchResultTy {
@@ -826,14 +832,26 @@ public:
Reg.RegNum);
}
- template <unsigned Class = AArch64::ZPRRegClassID>
- bool isSVEDataVectorReg() const {
- return (Kind == k_Register && Reg.Kind == RegKind::SVEDataVector) &&
+ template <unsigned Class> bool isSVEVectorReg() const {
+ RegKind RK;
+ switch (Class) {
+ case AArch64::ZPRRegClassID:
+ RK = RegKind::SVEDataVector;
+ break;
+ case AArch64::PPRRegClassID:
+ RK = RegKind::SVEPredicateVector;
+ break;
+ default:
+ llvm_unreachable("Unsupport register class");
+ }
+
+ return (Kind == k_Register && Reg.Kind == RK) &&
AArch64MCRegisterClasses[Class].contains(getReg());
}
- template <int ElementWidth> bool isSVEDataVectorRegOfWidth() const {
- return isSVEDataVectorReg() &&
+ template <int ElementWidth, unsigned Class>
+ bool isSVEVectorRegOfWidth() const {
+ return isSVEVectorReg<Class>() &&
(ElementWidth == -1 || Reg.ElementWidth == ElementWidth);
}
@@ -1926,6 +1944,27 @@ static unsigned matchSVEDataVectorRegName(StringRef Name) {
.Default(0);
}
+static unsigned matchSVEPredicateVectorRegName(StringRef Name) {
+ return StringSwitch<unsigned>(Name.lower())
+ .Case("p0", AArch64::P0)
+ .Case("p1", AArch64::P1)
+ .Case("p2", AArch64::P2)
+ .Case("p3", AArch64::P3)
+ .Case("p4", AArch64::P4)
+ .Case("p5", AArch64::P5)
+ .Case("p6", AArch64::P6)
+ .Case("p7", AArch64::P7)
+ .Case("p8", AArch64::P8)
+ .Case("p9", AArch64::P9)
+ .Case("p10", AArch64::P10)
+ .Case("p11", AArch64::P11)
+ .Case("p12", AArch64::P12)
+ .Case("p13", AArch64::P13)
+ .Case("p14", AArch64::P14)
+ .Case("p15", AArch64::P15)
+ .Default(0);
+}
+
static bool isValidSVEKind(StringRef Name) {
return StringSwitch<bool>(Name.lower())
.Case(".b", true)
@@ -1969,6 +2008,9 @@ unsigned AArch64AsmParser::matchRegisterNameAlias(StringRef Name,
if ((RegNum = matchSVEDataVectorRegName(Name)))
return Kind == RegKind::SVEDataVector ? RegNum : 0;
+ if ((RegNum = matchSVEPredicateVectorRegName(Name)))
+ return Kind == RegKind::SVEPredicateVector ? RegNum : 0;
+
if ((RegNum = MatchNeonVectorRegName(Name)))
return Kind == RegKind::NeonVector ? RegNum : 0;
@@ -2734,6 +2776,36 @@ AArch64AsmParser::tryParseSVERegister(int &Reg, StringRef &Kind,
return MatchOperand_NoMatch;
}
+/// tryParseSVEPredicateVector - Parse a SVE predicate register operand.
+OperandMatchResultTy
+AArch64AsmParser::tryParseSVEPredicateVector(OperandVector &Operands) {
+ // Check for a SVE predicate register specifier first.
+ const SMLoc S = getLoc();
+ StringRef Kind;
+ int RegNum = -1;
+ auto Res = tryParseSVERegister(RegNum, Kind, RegKind::SVEPredicateVector);
+ if (Res != MatchOperand_Success)
+ return Res;
+
+ unsigned ElementWidth = StringSwitch<unsigned>(Kind.lower())
+ .Case("", -1)
+ .Case(".b", 8)
+ .Case(".h", 16)
+ .Case(".s", 32)
+ .Case(".d", 64)
+ .Case(".q", 128)
+ .Default(0);
+
+ if (!ElementWidth)
+ return MatchOperand_NoMatch;
+
+ Operands.push_back(
+ AArch64Operand::CreateReg(RegNum, RegKind::SVEPredicateVector,
+ ElementWidth, S, getLoc(), getContext()));
+
+ return MatchOperand_Success;
+}
+
/// parseRegister - Parse a non-vector register operand.
bool AArch64AsmParser::parseRegister(OperandVector &Operands) {
SMLoc S = getLoc();
@@ -2954,9 +3026,12 @@ AArch64AsmParser::tryParseGPR64sp0Operand(OperandVector &Operands) {
bool AArch64AsmParser::parseOperand(OperandVector &Operands, bool isCondCode,
bool invertCondCode) {
MCAsmParser &Parser = getParser();
+
+ OperandMatchResultTy ResTy =
+ MatchOperandParserImpl(Operands, Mnemonic, /*ParseForAllFeatures=*/ true);
+
// Check if the current operand has a custom associated parser, if so, try to
// custom parse the operand, or fallback to the general approach.
- OperandMatchResultTy ResTy = MatchOperandParserImpl(Operands, Mnemonic);
if (ResTy == MatchOperand_Success)
return false;
// If there wasn't a custom match, try the generic matcher below. Otherwise,
@@ -3567,6 +3642,12 @@ bool AArch64AsmParser::showMatchError(SMLoc Loc, unsigned ErrCode,
ComputeAvailableFeatures(STI->getFeatureBits()));
return Error(Loc, "unrecognized instruction mnemonic" + Suggestion);
}
+ case Match_InvalidSVEPredicateAnyReg:
+ case Match_InvalidSVEPredicateBReg:
+ case Match_InvalidSVEPredicateHReg:
+ case Match_InvalidSVEPredicateSReg:
+ case Match_InvalidSVEPredicateDReg:
+ return Error(Loc, "invalid predicate register.");
default:
llvm_unreachable("unexpected error code!");
}
@@ -3991,6 +4072,11 @@ bool AArch64AsmParser::MatchAndEmitInstruction(SMLoc IDLoc, unsigned &Opcode,
case Match_InvalidLabel:
case Match_InvalidComplexRotationEven:
case Match_InvalidComplexRotationOdd:
+ case Match_InvalidSVEPredicateAnyReg:
+ case Match_InvalidSVEPredicateBReg:
+ case Match_InvalidSVEPredicateHReg:
+ case Match_InvalidSVEPredicateSReg:
+ case Match_InvalidSVEPredicateDReg:
case Match_MSR:
case Match_MRS: {
if (ErrorInfo >= Operands.size())
@@ -4341,6 +4427,20 @@ bool AArch64AsmParser::parseDirectiveReq(StringRef Name, SMLoc L) {
"sve vector register without type specifier expected");
}
+ if (RegNum == -1) {
+ StringRef Kind;
+ RegisterKind = RegKind::SVEPredicateVector;
+ OperandMatchResultTy Res =
+ tryParseSVERegister(RegNum, Kind, RegKind::SVEPredicateVector);
+
+ if (Res == MatchOperand_ParseFail)
+ return true;
+
+ if (Res == MatchOperand_Success && !Kind.empty())
+ return Error(SRegLoc,
+ "sve predicate register without type specifier expected");
+ }
+
if (RegNum == -1)
return Error(SRegLoc, "register name or alias expected");
diff --git a/llvm/lib/Target/AArch64/Disassembler/AArch64Disassembler.cpp b/llvm/lib/Target/AArch64/Disassembler/AArch64Disassembler.cpp
index aea1b4f2d2c..ae278caeda6 100644
--- a/llvm/lib/Target/AArch64/Disassembler/AArch64Disassembler.cpp
+++ b/llvm/lib/Target/AArch64/Disassembler/AArch64Disassembler.cpp
@@ -88,6 +88,9 @@ static DecodeStatus DecodeDDDDRegisterClass(MCInst &Inst, unsigned RegNo,
static DecodeStatus DecodeZPRRegisterClass(MCInst &Inst, unsigned RegNo,
uint64_t Address,
const void *Decode);
+static DecodeStatus DecodePPRRegisterClass(MCInst &Inst, unsigned RegNo,
+ uint64_t Address,
+ const void *Decode);
static DecodeStatus DecodeFixedPointScaleImm32(MCInst &Inst, unsigned Imm,
uint64_t Address,
@@ -461,6 +464,23 @@ static DecodeStatus DecodeZPRRegisterClass(MCInst &Inst, unsigned RegNo,
return Success;
}
+static const unsigned PPRDecoderTable[] = {
+ AArch64::P0, AArch64::P1, AArch64::P2, AArch64::P3,
+ AArch64::P4, AArch64::P5, AArch64::P6, AArch64::P7,
+ AArch64::P8, AArch64::P9, AArch64::P10, AArch64::P11,
+ AArch64::P12, AArch64::P13, AArch64::P14, AArch64::P15
+};
+
+static DecodeStatus DecodePPRRegisterClass(MCInst &Inst, unsigned RegNo,
+ uint64_t Addr, const void *Decoder) {
+ if (RegNo > 15)
+ return Fail;
+
+ unsigned Register = PPRDecoderTable[RegNo];
+ Inst.addOperand(MCOperand::createReg(Register));
+ return Success;
+}
+
static const unsigned VectorDecoderTable[] = {
AArch64::Q0, AArch64::Q1, AArch64::Q2, AArch64::Q3, AArch64::Q4,
AArch64::Q5, AArch64::Q6, AArch64::Q7, AArch64::Q8, AArch64::Q9,
diff --git a/llvm/lib/Target/AArch64/SVEInstrFormats.td b/llvm/lib/Target/AArch64/SVEInstrFormats.td
index b4b46d731e3..15c1275f259 100644
--- a/llvm/lib/Target/AArch64/SVEInstrFormats.td
+++ b/llvm/lib/Target/AArch64/SVEInstrFormats.td
@@ -39,3 +39,65 @@ multiclass sve_int_bin_cons_arit_0<bits<3> opc, string asm> {
def _S : sve_int_bin_cons_arit_0<0b10, opc, asm, ZPR32>;
def _D : sve_int_bin_cons_arit_0<0b11, opc, asm, ZPR64>;
}
+
+//===----------------------------------------------------------------------===//
+// SVE Permute - In Lane Group
+//===----------------------------------------------------------------------===//
+
+class sve_int_perm_bin_perm_zz<bits<3> opc, bits<2> sz8_64, string asm,
+ ZPRRegOp zprty>
+: I<(outs zprty:$Zd), (ins zprty:$Zn, zprty:$Zm),
+ asm, "\t$Zd, $Zn, $Zm",
+ "",
+ []>, Sched<[]> {
+ bits<5> Zd;
+ bits<5> Zm;
+ bits<5> Zn;
+ let Inst{31-24} = 0b00000101;
+ let Inst{23-22} = sz8_64;
+ let Inst{21} = 0b1;
+ let Inst{20-16} = Zm;
+ let Inst{15-13} = 0b011;
+ let Inst{12-10} = opc;
+ let Inst{9-5} = Zn;
+ let Inst{4-0} = Zd;
+}
+
+multiclass sve_int_perm_bin_perm_zz<bits<3> opc, string asm> {
+ def _B : sve_int_perm_bin_perm_zz<opc, 0b00, asm, ZPR8>;
+ def _H : sve_int_perm_bin_perm_zz<opc, 0b01, asm, ZPR16>;
+ def _S : sve_int_perm_bin_perm_zz<opc, 0b10, asm, ZPR32>;
+ def _D : sve_int_perm_bin_perm_zz<opc, 0b11, asm, ZPR64>;
+}
+
+//===----------------------------------------------------------------------===//
+// SVE Permute - Predicates Group
+//===----------------------------------------------------------------------===//
+
+class sve_int_perm_bin_perm_pp<bits<3> opc, bits<2> sz8_64, string asm,
+ PPRRegOp pprty>
+: I<(outs pprty:$Pd), (ins pprty:$Pn, pprty:$Pm),
+ asm, "\t$Pd, $Pn, $Pm",
+ "",
+ []>, Sched<[]> {
+ bits<4> Pd;
+ bits<4> Pm;
+ bits<4> Pn;
+ let Inst{31-24} = 0b00000101;
+ let Inst{23-22} = sz8_64;
+ let Inst{21-20} = 0b10;
+ let Inst{19-16} = Pm;
+ let Inst{15-13} = 0b010;
+ let Inst{12-10} = opc;
+ let Inst{9} = 0b0;
+ let Inst{8-5} = Pn;
+ let Inst{4} = 0b0;
+ let Inst{3-0} = Pd;
+}
+
+multiclass sve_int_perm_bin_perm_pp<bits<3> opc, string asm> {
+ def _B : sve_int_perm_bin_perm_pp<opc, 0b00, asm, PPR8>;
+ def _H : sve_int_perm_bin_perm_pp<opc, 0b01, asm, PPR16>;
+ def _S : sve_int_perm_bin_perm_pp<opc, 0b10, asm, PPR32>;
+ def _D : sve_int_perm_bin_perm_pp<opc, 0b11, asm, PPR64>;
+} \ No newline at end of file
OpenPOWER on IntegriCloud