[llvm] r319315 - [AArch64][SVE] Asm: Add SVE predicate register definitions and parsing support

Sander de Smalen via llvm-commits llvm-commits at lists.llvm.org
Wed Nov 29 06:34:18 PST 2017


Author: s.desmalen
Date: Wed Nov 29 06:34:18 2017
New Revision: 319315

URL: http://llvm.org/viewvc/llvm-project?rev=319315&view=rev
Log:
[AArch64][SVE] Asm: Add SVE predicate register definitions and parsing support

Summary: Patch [1/4] in a series to add parsing of predicates and properly parse SVE ZIP1/ZIP2 instructions.

Reviewers: rengolin, kristof.beyls, fhahn, mcrosier, evandro, echristo, efriedma

Reviewed By: fhahn

Subscribers: aemerson, javed.absar, llvm-commits, tschuett

Differential Revision: https://reviews.llvm.org/D40360

Added:
    llvm/trunk/test/MC/AArch64/SVE/dot-req-diagnostics.s
    llvm/trunk/test/MC/AArch64/SVE/dot-req.s
Modified:
    llvm/trunk/lib/Target/AArch64/AArch64RegisterInfo.td
    llvm/trunk/lib/Target/AArch64/AsmParser/AArch64AsmParser.cpp
    llvm/trunk/lib/Target/AArch64/Disassembler/AArch64Disassembler.cpp

Modified: llvm/trunk/lib/Target/AArch64/AArch64RegisterInfo.td
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Target/AArch64/AArch64RegisterInfo.td?rev=319315&r1=319314&r2=319315&view=diff
==============================================================================
--- llvm/trunk/lib/Target/AArch64/AArch64RegisterInfo.td (original)
+++ llvm/trunk/lib/Target/AArch64/AArch64RegisterInfo.td Wed Nov 29 06:34:18 2017
@@ -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, AsmOperan
   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") # ">";

Modified: llvm/trunk/lib/Target/AArch64/AsmParser/AArch64AsmParser.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Target/AArch64/AsmParser/AArch64AsmParser.cpp?rev=319315&r1=319314&r2=319315&view=diff
==============================================================================
--- llvm/trunk/lib/Target/AArch64/AsmParser/AArch64AsmParser.cpp (original)
+++ llvm/trunk/lib/Target/AArch64/AsmParser/AArch64AsmParser.cpp Wed Nov 29 06:34:18 2017
@@ -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 matchSVEDataVectorRegNam
       .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)
@@ -1936,8 +1975,8 @@ static bool isValidSVEKind(StringRef Nam
       .Default(false);
 }
 
-static bool isSVEDataVectorRegister(StringRef Name) {
-  return Name[0] == 'z';
+static bool isSVERegister(StringRef Name) {
+  return Name[0] == 'z' || Name[0] == 'p';
 }
 
 static void parseValidVectorKind(StringRef Name, unsigned &NumElements,
@@ -1980,6 +2019,9 @@ unsigned AArch64AsmParser::matchRegister
   case RegKind::SVEDataVector:
     RegNum = matchSVEDataVectorRegName(Name);
     break;
+  case RegKind::SVEPredicateVector:
+    RegNum = matchSVEPredicateVectorRegName(Name);
+    break;
   }
 
   if (!RegNum) {
@@ -2007,7 +2049,7 @@ int AArch64AsmParser::tryParseRegister()
     return -1;
 
   std::string lowerCase = Tok.getString().lower();
-  if (isSVEDataVectorRegister(lowerCase))
+  if (isSVERegister(lowerCase))
     return -1;
 
   unsigned RegNum = matchRegisterNameAlias(lowerCase, RegKind::Scalar);
@@ -2742,6 +2784,36 @@ AArch64AsmParser::tryParseSVERegister(in
   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();
@@ -3575,6 +3647,12 @@ bool AArch64AsmParser::showMatchError(SM
         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!");
   }
@@ -3974,6 +4052,11 @@ bool AArch64AsmParser::MatchAndEmitInstr
   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())
@@ -4324,6 +4407,20 @@ bool AArch64AsmParser::parseDirectiveReq
                    "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");
 

Modified: llvm/trunk/lib/Target/AArch64/Disassembler/AArch64Disassembler.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Target/AArch64/Disassembler/AArch64Disassembler.cpp?rev=319315&r1=319314&r2=319315&view=diff
==============================================================================
--- llvm/trunk/lib/Target/AArch64/Disassembler/AArch64Disassembler.cpp (original)
+++ llvm/trunk/lib/Target/AArch64/Disassembler/AArch64Disassembler.cpp Wed Nov 29 06:34:18 2017
@@ -88,6 +88,9 @@ static DecodeStatus DecodeDDDDRegisterCl
 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,
@@ -460,6 +463,23 @@ static DecodeStatus DecodeZPRRegisterCla
   Inst.addOperand(MCOperand::createReg(Register));
   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,

Added: llvm/trunk/test/MC/AArch64/SVE/dot-req-diagnostics.s
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/MC/AArch64/SVE/dot-req-diagnostics.s?rev=319315&view=auto
==============================================================================
--- llvm/trunk/test/MC/AArch64/SVE/dot-req-diagnostics.s (added)
+++ llvm/trunk/test/MC/AArch64/SVE/dot-req-diagnostics.s Wed Nov 29 06:34:18 2017
@@ -0,0 +1,20 @@
+// RUN: not llvm-mc -triple aarch64-none-linux-gnu -mattr=+sve < %s 2>&1 | FileCheck --check-prefix=CHECK --check-prefix=CHECK-ERROR %s
+
+foo:
+// CHECK: error: sve predicate register without type specifier expected
+  pbarb .req p1.b
+// CHECK: error: sve predicate register without type specifier expected
+  pbarh .req p1.h
+// CHECK: error: sve predicate register without type specifier expected
+  pbars .req p1.s
+// CHECK: error: sve predicate register without type specifier expected
+  pbard .req p1.d
+
+// CHECK: error: sve vector register without type specifier expected
+  zbarb .req z1.b
+// CHECK: error: sve vector register without type specifier expected
+  zbarh .req z1.h
+// CHECK: error: sve vector register without type specifier expected
+  zbars .req z1.s
+// CHECK: error: sve vector register without type specifier expected
+  zbard .req z1.d

Added: llvm/trunk/test/MC/AArch64/SVE/dot-req.s
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/MC/AArch64/SVE/dot-req.s?rev=319315&view=auto
==============================================================================
--- llvm/trunk/test/MC/AArch64/SVE/dot-req.s (added)
+++ llvm/trunk/test/MC/AArch64/SVE/dot-req.s Wed Nov 29 06:34:18 2017
@@ -0,0 +1,9 @@
+// RUN: llvm-mc -triple=aarch64-none-linux-gnu -mattr=+sve -show-encoding < %s 2>&1 | FileCheck %s
+
+foo:
+// CHECK-NOT: error:
+  pbar .req p1
+
+// CHECK: add z0.s, z1.s, z2.s
+  zbar .req z1
+  add  z0.s, zbar.s, z2.s




More information about the llvm-commits mailing list