Skip to content

Commit ce1e097

Browse files
committedDec 18, 2017
[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 llvm-svn: 320970
1 parent 45fda90 commit ce1e097

File tree

5 files changed

+207
-10
lines changed

5 files changed

+207
-10
lines changed
 

‎llvm/lib/Target/AArch64/AArch64RegisterInfo.td

+52-1
Original file line numberDiff line numberDiff line change
@@ -652,6 +652,24 @@ def XSeqPairClassOperand :
652652

653653
//===----- END: v8.1a atomic CASP register operands -----------------------===//
654654

655+
// SVE predicate registers
656+
def P0 : AArch64Reg<0, "p0">, DwarfRegNum<[48]>;
657+
def P1 : AArch64Reg<1, "p1">, DwarfRegNum<[49]>;
658+
def P2 : AArch64Reg<2, "p2">, DwarfRegNum<[50]>;
659+
def P3 : AArch64Reg<3, "p3">, DwarfRegNum<[51]>;
660+
def P4 : AArch64Reg<4, "p4">, DwarfRegNum<[52]>;
661+
def P5 : AArch64Reg<5, "p5">, DwarfRegNum<[53]>;
662+
def P6 : AArch64Reg<6, "p6">, DwarfRegNum<[54]>;
663+
def P7 : AArch64Reg<7, "p7">, DwarfRegNum<[55]>;
664+
def P8 : AArch64Reg<8, "p8">, DwarfRegNum<[56]>;
665+
def P9 : AArch64Reg<9, "p9">, DwarfRegNum<[57]>;
666+
def P10 : AArch64Reg<10, "p10">, DwarfRegNum<[58]>;
667+
def P11 : AArch64Reg<11, "p11">, DwarfRegNum<[59]>;
668+
def P12 : AArch64Reg<12, "p12">, DwarfRegNum<[60]>;
669+
def P13 : AArch64Reg<13, "p13">, DwarfRegNum<[61]>;
670+
def P14 : AArch64Reg<14, "p14">, DwarfRegNum<[62]>;
671+
def P15 : AArch64Reg<15, "p15">, DwarfRegNum<[63]>;
672+
655673
// The part of SVE registers that don't overlap Neon registers.
656674
// These are only used as part of clobber lists.
657675
def Z0_HI : AArch64Reg<0, "z0_hi">;
@@ -731,11 +749,43 @@ class SVERegOp <string Suffix, AsmOperandClass C,
731749
let ParserMatchClass = C;
732750
}
733751

752+
class PPRRegOp <string Suffix, AsmOperandClass C,
753+
RegisterClass RC> : SVERegOp<Suffix, C, RC> {}
734754
class ZPRRegOp <string Suffix, AsmOperandClass C,
735755
RegisterClass RC> : SVERegOp<Suffix, C, RC> {}
736756

737757
//******************************************************************************
738758

759+
// SVE predicate register class.
760+
def PPR : RegisterClass<"AArch64",
761+
[nxv16i1, nxv8i1, nxv4i1, nxv2i1],
762+
16, (sequence "P%u", 0, 15)> {
763+
let Size = 16;
764+
}
765+
766+
class PPRAsmOperand <string name, int Width>: AsmOperandClass {
767+
let Name = "SVE" # name # "Reg";
768+
let PredicateMethod = "isSVEVectorRegOfWidth<"
769+
# Width # ", AArch64::PPRRegClassID>";
770+
let DiagnosticType = "InvalidSVE" # name # "Reg";
771+
let RenderMethod = "addRegOperands";
772+
let ParserMethod = "tryParseSVEPredicateVector";
773+
}
774+
775+
def PPRAsmOpAny : PPRAsmOperand<"PredicateAny", -1>;
776+
def PPRAsmOp8 : PPRAsmOperand<"PredicateB", 8>;
777+
def PPRAsmOp16 : PPRAsmOperand<"PredicateH", 16>;
778+
def PPRAsmOp32 : PPRAsmOperand<"PredicateS", 32>;
779+
def PPRAsmOp64 : PPRAsmOperand<"PredicateD", 64>;
780+
781+
def PPRAny : PPRRegOp<"", PPRAsmOpAny, PPR>;
782+
def PPR8 : PPRRegOp<"b", PPRAsmOp8, PPR>;
783+
def PPR16 : PPRRegOp<"h", PPRAsmOp16, PPR>;
784+
def PPR32 : PPRRegOp<"s", PPRAsmOp32, PPR>;
785+
def PPR64 : PPRRegOp<"d", PPRAsmOp64, PPR>;
786+
787+
//******************************************************************************
788+
739789
// SVE vector register class
740790
def ZPR : RegisterClass<"AArch64",
741791
[nxv16i8, nxv8i16, nxv4i32, nxv2i64,
@@ -748,7 +798,8 @@ def ZPR : RegisterClass<"AArch64",
748798

749799
class ZPRAsmOperand <string name, int Width>: AsmOperandClass {
750800
let Name = "SVE" # name # "Reg";
751-
let PredicateMethod = "isSVEDataVectorRegOfWidth<" # Width # ">";
801+
let PredicateMethod = "isSVEVectorRegOfWidth<"
802+
# Width # ", AArch64::ZPRRegClassID>";
752803
let RenderMethod = "addRegOperands";
753804
let ParserMethod = "tryParseSVEDataVector<"
754805
# !if(!eq(Width, -1), "false", "true") # ">";

‎llvm/lib/Target/AArch64/AsmParser/AArch64AsmParser.cpp

+106-9
Original file line numberDiff line numberDiff line change
@@ -59,7 +59,12 @@ using namespace llvm;
5959

6060
namespace {
6161

62-
enum class RegKind {Scalar, NeonVector, SVEDataVector};
62+
enum class RegKind {
63+
Scalar,
64+
NeonVector,
65+
SVEDataVector,
66+
SVEPredicateVector
67+
};
6368

6469
class AArch64AsmParser : public MCTargetAsmParser {
6570
private:
@@ -134,6 +139,7 @@ class AArch64AsmParser : public MCTargetAsmParser {
134139
OperandMatchResultTy tryParseGPRSeqPair(OperandVector &Operands);
135140
template <bool ParseSuffix>
136141
OperandMatchResultTy tryParseSVEDataVector(OperandVector &Operands);
142+
OperandMatchResultTy tryParseSVEPredicateVector(OperandVector &Operands);
137143

138144
public:
139145
enum AArch64MatchResultTy {
@@ -826,14 +832,26 @@ class AArch64Operand : public MCParsedAsmOperand {
826832
Reg.RegNum);
827833
}
828834

829-
template <unsigned Class = AArch64::ZPRRegClassID>
830-
bool isSVEDataVectorReg() const {
831-
return (Kind == k_Register && Reg.Kind == RegKind::SVEDataVector) &&
835+
template <unsigned Class> bool isSVEVectorReg() const {
836+
RegKind RK;
837+
switch (Class) {
838+
case AArch64::ZPRRegClassID:
839+
RK = RegKind::SVEDataVector;
840+
break;
841+
case AArch64::PPRRegClassID:
842+
RK = RegKind::SVEPredicateVector;
843+
break;
844+
default:
845+
llvm_unreachable("Unsupport register class");
846+
}
847+
848+
return (Kind == k_Register && Reg.Kind == RK) &&
832849
AArch64MCRegisterClasses[Class].contains(getReg());
833850
}
834851

835-
template <int ElementWidth> bool isSVEDataVectorRegOfWidth() const {
836-
return isSVEDataVectorReg() &&
852+
template <int ElementWidth, unsigned Class>
853+
bool isSVEVectorRegOfWidth() const {
854+
return isSVEVectorReg<Class>() &&
837855
(ElementWidth == -1 || Reg.ElementWidth == ElementWidth);
838856
}
839857

@@ -1926,6 +1944,27 @@ static unsigned matchSVEDataVectorRegName(StringRef Name) {
19261944
.Default(0);
19271945
}
19281946

1947+
static unsigned matchSVEPredicateVectorRegName(StringRef Name) {
1948+
return StringSwitch<unsigned>(Name.lower())
1949+
.Case("p0", AArch64::P0)
1950+
.Case("p1", AArch64::P1)
1951+
.Case("p2", AArch64::P2)
1952+
.Case("p3", AArch64::P3)
1953+
.Case("p4", AArch64::P4)
1954+
.Case("p5", AArch64::P5)
1955+
.Case("p6", AArch64::P6)
1956+
.Case("p7", AArch64::P7)
1957+
.Case("p8", AArch64::P8)
1958+
.Case("p9", AArch64::P9)
1959+
.Case("p10", AArch64::P10)
1960+
.Case("p11", AArch64::P11)
1961+
.Case("p12", AArch64::P12)
1962+
.Case("p13", AArch64::P13)
1963+
.Case("p14", AArch64::P14)
1964+
.Case("p15", AArch64::P15)
1965+
.Default(0);
1966+
}
1967+
19291968
static bool isValidSVEKind(StringRef Name) {
19301969
return StringSwitch<bool>(Name.lower())
19311970
.Case(".b", true)
@@ -1936,8 +1975,8 @@ static bool isValidSVEKind(StringRef Name) {
19361975
.Default(false);
19371976
}
19381977

1939-
static bool isSVEDataVectorRegister(StringRef Name) {
1940-
return Name[0] == 'z';
1978+
static bool isSVERegister(StringRef Name) {
1979+
return Name[0] == 'z' || Name[0] == 'p';
19411980
}
19421981

19431982
static void parseValidVectorKind(StringRef Name, unsigned &NumElements,
@@ -1980,6 +2019,9 @@ unsigned AArch64AsmParser::matchRegisterNameAlias(StringRef Name,
19802019
case RegKind::SVEDataVector:
19812020
RegNum = matchSVEDataVectorRegName(Name);
19822021
break;
2022+
case RegKind::SVEPredicateVector:
2023+
RegNum = matchSVEPredicateVectorRegName(Name);
2024+
break;
19832025
}
19842026

19852027
if (!RegNum) {
@@ -2007,7 +2049,7 @@ int AArch64AsmParser::tryParseRegister() {
20072049
return -1;
20082050

20092051
std::string lowerCase = Tok.getString().lower();
2010-
if (isSVEDataVectorRegister(lowerCase))
2052+
if (isSVERegister(lowerCase))
20112053
return -1;
20122054

20132055
unsigned RegNum = matchRegisterNameAlias(lowerCase, RegKind::Scalar);
@@ -2742,6 +2784,36 @@ AArch64AsmParser::tryParseSVERegister(int &Reg, StringRef &Kind,
27422784
return MatchOperand_NoMatch;
27432785
}
27442786

2787+
/// tryParseSVEPredicateVector - Parse a SVE predicate register operand.
2788+
OperandMatchResultTy
2789+
AArch64AsmParser::tryParseSVEPredicateVector(OperandVector &Operands) {
2790+
// Check for a SVE predicate register specifier first.
2791+
const SMLoc S = getLoc();
2792+
StringRef Kind;
2793+
int RegNum = -1;
2794+
auto Res = tryParseSVERegister(RegNum, Kind, RegKind::SVEPredicateVector);
2795+
if (Res != MatchOperand_Success)
2796+
return Res;
2797+
2798+
unsigned ElementWidth = StringSwitch<unsigned>(Kind.lower())
2799+
.Case("", -1)
2800+
.Case(".b", 8)
2801+
.Case(".h", 16)
2802+
.Case(".s", 32)
2803+
.Case(".d", 64)
2804+
.Case(".q", 128)
2805+
.Default(0);
2806+
2807+
if (!ElementWidth)
2808+
return MatchOperand_NoMatch;
2809+
2810+
Operands.push_back(
2811+
AArch64Operand::CreateReg(RegNum, RegKind::SVEPredicateVector,
2812+
ElementWidth, S, getLoc(), getContext()));
2813+
2814+
return MatchOperand_Success;
2815+
}
2816+
27452817
/// parseRegister - Parse a non-vector register operand.
27462818
bool AArch64AsmParser::parseRegister(OperandVector &Operands) {
27472819
SMLoc S = getLoc();
@@ -3575,6 +3647,12 @@ bool AArch64AsmParser::showMatchError(SMLoc Loc, unsigned ErrCode,
35753647
ComputeAvailableFeatures(STI->getFeatureBits()));
35763648
return Error(Loc, "unrecognized instruction mnemonic" + Suggestion);
35773649
}
3650+
case Match_InvalidSVEPredicateAnyReg:
3651+
case Match_InvalidSVEPredicateBReg:
3652+
case Match_InvalidSVEPredicateHReg:
3653+
case Match_InvalidSVEPredicateSReg:
3654+
case Match_InvalidSVEPredicateDReg:
3655+
return Error(Loc, "invalid predicate register.");
35783656
default:
35793657
llvm_unreachable("unexpected error code!");
35803658
}
@@ -3999,6 +4077,11 @@ bool AArch64AsmParser::MatchAndEmitInstruction(SMLoc IDLoc, unsigned &Opcode,
39994077
case Match_InvalidLabel:
40004078
case Match_InvalidComplexRotationEven:
40014079
case Match_InvalidComplexRotationOdd:
4080+
case Match_InvalidSVEPredicateAnyReg:
4081+
case Match_InvalidSVEPredicateBReg:
4082+
case Match_InvalidSVEPredicateHReg:
4083+
case Match_InvalidSVEPredicateSReg:
4084+
case Match_InvalidSVEPredicateDReg:
40024085
case Match_MSR:
40034086
case Match_MRS: {
40044087
if (ErrorInfo >= Operands.size())
@@ -4349,6 +4432,20 @@ bool AArch64AsmParser::parseDirectiveReq(StringRef Name, SMLoc L) {
43494432
"sve vector register without type specifier expected");
43504433
}
43514434

4435+
if (RegNum == -1) {
4436+
StringRef Kind;
4437+
RegisterKind = RegKind::SVEPredicateVector;
4438+
OperandMatchResultTy Res =
4439+
tryParseSVERegister(RegNum, Kind, RegKind::SVEPredicateVector);
4440+
4441+
if (Res == MatchOperand_ParseFail)
4442+
return true;
4443+
4444+
if (Res == MatchOperand_Success && !Kind.empty())
4445+
return Error(SRegLoc,
4446+
"sve predicate register without type specifier expected");
4447+
}
4448+
43524449
if (RegNum == -1)
43534450
return Error(SRegLoc, "register name or alias expected");
43544451

‎llvm/lib/Target/AArch64/Disassembler/AArch64Disassembler.cpp

+20
Original file line numberDiff line numberDiff line change
@@ -88,6 +88,9 @@ static DecodeStatus DecodeDDDDRegisterClass(MCInst &Inst, unsigned RegNo,
8888
static DecodeStatus DecodeZPRRegisterClass(MCInst &Inst, unsigned RegNo,
8989
uint64_t Address,
9090
const void *Decode);
91+
static DecodeStatus DecodePPRRegisterClass(MCInst &Inst, unsigned RegNo,
92+
uint64_t Address,
93+
const void *Decode);
9194

9295
static DecodeStatus DecodeFixedPointScaleImm32(MCInst &Inst, unsigned Imm,
9396
uint64_t Address,
@@ -461,6 +464,23 @@ static DecodeStatus DecodeZPRRegisterClass(MCInst &Inst, unsigned RegNo,
461464
return Success;
462465
}
463466

467+
static const unsigned PPRDecoderTable[] = {
468+
AArch64::P0, AArch64::P1, AArch64::P2, AArch64::P3,
469+
AArch64::P4, AArch64::P5, AArch64::P6, AArch64::P7,
470+
AArch64::P8, AArch64::P9, AArch64::P10, AArch64::P11,
471+
AArch64::P12, AArch64::P13, AArch64::P14, AArch64::P15
472+
};
473+
474+
static DecodeStatus DecodePPRRegisterClass(MCInst &Inst, unsigned RegNo,
475+
uint64_t Addr, const void *Decoder) {
476+
if (RegNo > 15)
477+
return Fail;
478+
479+
unsigned Register = PPRDecoderTable[RegNo];
480+
Inst.addOperand(MCOperand::createReg(Register));
481+
return Success;
482+
}
483+
464484
static const unsigned VectorDecoderTable[] = {
465485
AArch64::Q0, AArch64::Q1, AArch64::Q2, AArch64::Q3, AArch64::Q4,
466486
AArch64::Q5, AArch64::Q6, AArch64::Q7, AArch64::Q8, AArch64::Q9,
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
// RUN: not llvm-mc -triple aarch64-none-linux-gnu -mattr=+sve < %s 2>&1 | FileCheck --check-prefix=CHECK --check-prefix=CHECK-ERROR %s
2+
3+
foo:
4+
// CHECK: error: sve predicate register without type specifier expected
5+
pbarb .req p1.b
6+
// CHECK: error: sve predicate register without type specifier expected
7+
pbarh .req p1.h
8+
// CHECK: error: sve predicate register without type specifier expected
9+
pbars .req p1.s
10+
// CHECK: error: sve predicate register without type specifier expected
11+
pbard .req p1.d
12+
13+
// CHECK: error: sve vector register without type specifier expected
14+
zbarb .req z1.b
15+
// CHECK: error: sve vector register without type specifier expected
16+
zbarh .req z1.h
17+
// CHECK: error: sve vector register without type specifier expected
18+
zbars .req z1.s
19+
// CHECK: error: sve vector register without type specifier expected
20+
zbard .req z1.d

‎llvm/test/MC/AArch64/SVE/dot-req.s

+9
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
// RUN: llvm-mc -triple=aarch64-none-linux-gnu -mattr=+sve -show-encoding < %s 2>&1 | FileCheck %s
2+
3+
foo:
4+
// CHECK-NOT: error:
5+
pbar .req p1
6+
7+
// CHECK: add z0.s, z1.s, z2.s
8+
zbar .req z1
9+
add z0.s, zbar.s, z2.s

0 commit comments

Comments
 (0)
Please sign in to comment.